aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-10-06 23:00:33 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-10-06 23:00:33 +0000
commitb001de7458d17c17e6d8b8034c7cfcefd3b70c00 (patch)
tree22aafdcc75a1bc4984c7112800b87ece9b2f54c6
parent5f22614327065a4ae78588eda8cb62f8b50502aa (diff)
Support for C1x _Atomic specifier (see testcase). This is primarily being committed at the moment to help support C++0x <atomic>, but it should be a solid base for implementing the full specification of C1x _Atomic.
Thanks to Jeffrey Yasskin for the thorough review! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141330 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h8
-rw-r--r--include/clang/AST/Type.h35
-rw-r--r--include/clang/AST/TypeLoc.h56
-rw-r--r--include/clang/AST/TypeNodes.def3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--include/clang/Basic/Specifiers.h1
-rw-r--r--include/clang/Basic/TokenKinds.def1
-rw-r--r--include/clang/Parse/Parser.h3
-rw-r--r--include/clang/Sema/DeclSpec.h3
-rw-r--r--include/clang/Sema/Sema.h1
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/AST/ASTContext.cpp57
-rw-r--r--lib/AST/ASTImporter.cpp10
-rw-r--r--lib/AST/ItaniumMangle.cpp8
-rw-r--r--lib/AST/MicrosoftMangle.cpp4
-rw-r--r--lib/AST/Type.cpp2
-rw-r--r--lib/AST/TypePrinter.cpp11
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp10
-rw-r--r--lib/CodeGen/CGDebugInfo.h1
-rw-r--r--lib/CodeGen/CGRTTI.cpp5
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp8
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp58
-rw-r--r--lib/Parse/ParseTentative.cpp5
-rw-r--r--lib/Sema/DeclSpec.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp12
-rw-r--r--lib/Sema/SemaLookup.cpp6
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp19
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp3
-rw-r--r--lib/Sema/SemaType.cpp47
-rw-r--r--lib/Sema/TreeTransform.h35
-rw-r--r--lib/Serialization/ASTReader.cpp14
-rw-r--r--lib/Serialization/ASTWriter.cpp12
-rw-r--r--test/Sema/atomic-type.c22
-rw-r--r--tools/libclang/CIndex.cpp4
39 files changed, 483 insertions, 9 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a18a45eb40..09defdb31e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -120,6 +120,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
mutable llvm::FoldingSet<AutoType> AutoTypes;
+ mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
@@ -601,6 +602,10 @@ public:
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
+ /// getAtomicType - Return the uniqued reference to the atomic type for
+ /// the specified type.
+ QualType getAtomicType(QualType T) const;
+
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
QualType getBlockPointerType(QualType T) const;
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 36add6c457..a224bb0a40 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -813,6 +813,10 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
+DEF_TRAVERSE_TYPE(AtomicType, {
+ TRY_TO(TraverseType(T->getValueType()));
+ })
+
#undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal -----------------
@@ -1041,6 +1045,10 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+DEF_TRAVERSE_TYPELOC(AtomicType, {
+ TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
+ })
+
#undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal -----------------
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 0b4c8f715d..4a44710938 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -1449,6 +1449,7 @@ public:
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
+ bool isAtomicType() const; // C1X _Atomic()
/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
@@ -4352,6 +4353,37 @@ public:
static bool classof(const ObjCObjectPointerType *) { return true; }
};
+class AtomicType : public Type, public llvm::FoldingSetNode {
+ QualType ValueType;
+
+ AtomicType(QualType ValTy, QualType Canonical)
+ : Type(Atomic, Canonical, ValTy->isDependentType(),
+ ValTy->isInstantiationDependentType(),
+ ValTy->isVariablyModifiedType(),
+ ValTy->containsUnexpandedParameterPack()),
+ ValueType(ValTy) {}
+ friend class ASTContext; // ASTContext creates these.
+
+ public:
+ /// getValueType - Gets the type contained by this atomic type, i.e.
+ /// the type returned by performing an atomic load of this atomic type.
+ QualType getValueType() const { return ValueType; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getValueType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Atomic;
+ }
+ static bool classof(const AtomicType *) { return true; }
+};
+
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
public:
@@ -4677,6 +4709,9 @@ inline bool Type::isObjCObjectOrInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType) ||
isa<ObjCObjectType>(CanonicalType);
}
+inline bool Type::isAtomicType() const {
+ return isa<AtomicType>(CanonicalType);
+}
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 8e3e8d37c8..02ced65e5c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1730,6 +1730,62 @@ public:
}
};
+struct AtomicTypeLocInfo {
+ SourceLocation KWLoc, LParenLoc, RParenLoc;
+};
+
+class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
+ AtomicType, AtomicTypeLocInfo> {
+public:
+ TypeLoc getValueLoc() const {
+ return this->getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getKWLoc(), getRParenLoc());
+ }
+
+ SourceLocation getKWLoc() const {
+ return this->getLocalData()->KWLoc;
+ }
+ void setKWLoc(SourceLocation Loc) {
+ this->getLocalData()->KWLoc = Loc;
+ }
+
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getParensRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+ void setParensRange(SourceRange Range) {
+ setLParenLoc(Range.getBegin());
+ setRParenLoc(Range.getEnd());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getValueType();
+ }
+};
+
+
}
#endif
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 0792d0d9b3..d5c485f8a3 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -102,9 +102,10 @@ DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
+TYPE(Atomic, Type)
#ifdef LAST_TYPE
-LAST_TYPE(ObjCObjectPointer)
+LAST_TYPE(Atomic)
#undef LAST_TYPE
#endif
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d4c118b447..411d49c912 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3073,6 +3073,10 @@ def err_block_with_return_type_requires_args : Error<
"block with explicit return type requires argument list">;
def err_func_def_incomplete_result : Error<
"incomplete result type %0 in function definition">;
+def err_atomic_specifier_bad_type : Error<
+ "_Atomic cannot be applied to "
+ "%select{incomplete |array |function |reference |atomic |qualified |}0type "
+ "%1 %select{||||||which is not trivially copyable}0">;
// Expressions.
def ext_sizeof_function_type : Extension<
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index be59ec5a56..1e89a8c817 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -57,6 +57,7 @@ namespace clang {
TST_underlyingType, // __underlying_type for C++0x
TST_auto, // C++0x auto
TST_unknown_anytype, // __unknown_anytype extension
+ TST_atomic, // C1X _Atomic
TST_error // erroneous type
};
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 1256caabec..151a75d1e7 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -250,6 +250,7 @@ KEYWORD(void , KEYALL)
KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
+KEYWORD(_Atomic , KEYALL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
KEYWORD(_Generic , KEYALL)
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index e8494767b5..cf9bbbe9dd 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1768,7 +1768,8 @@ private:
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
-
+ void ParseAtomicSpecifier(DeclSpec &DS);
+
ExprResult ParseAlignArgument(SourceLocation Start);
void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation *endLoc = 0);
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 645ddcb468..3f11ee4f55 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -260,6 +260,7 @@ public:
static const TST TST_underlyingType = clang::TST_underlyingType;
static const TST TST_auto = clang::TST_auto;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
+ static const TST TST_atomic = clang::TST_atomic;
static const TST TST_error = clang::TST_error;
// type-qualifiers
@@ -356,7 +357,7 @@ private:
static bool isTypeRep(TST T) {
return (T == TST_typename || T == TST_typeofType ||
- T == TST_underlyingType);
+ T == TST_underlyingType || T == TST_atomic);
}
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index aad52fcab8..4b8bbdc6ea 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -793,6 +793,7 @@ public:
QualType BuildBlockPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
QualType BuildParenType(QualType T);
+ QualType BuildAtomicType(QualType T, SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index b8db49e76a..9a8eba2427 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -647,7 +647,9 @@ namespace clang {
/// \brief A AutoType record.
TYPE_AUTO = 38,
/// \brief A UnaryTransformType record.
- TYPE_UNARY_TRANSFORM = 39
+ TYPE_UNARY_TRANSFORM = 39,
+ /// \brief An AtomicType record.
+ TYPE_ATOMIC = 40
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 055ed7c08c..3377799e3d 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1063,6 +1063,11 @@ ASTContext::getTypeInfo(const Type *T) const {
return getTypeInfo(getCanonicalType(T));
}
+ case Type::Atomic: {
+ // FIXME: The alignment needs to be "fixed".
+ return getTypeInfo(cast<AtomicType>(T)->getValueType());
+ }
+
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
@@ -1707,6 +1712,12 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
break;
}
+ case Type::Atomic: {
+ const AtomicType *at = cast<AtomicType>(ty);
+ result = getAtomicType(getVariableArrayDecayedType(at->getValueType()));
+ break;
+ }
+
case Type::ConstantArray: {
const ConstantArrayType *cat = cast<ConstantArrayType>(ty);
result = getConstantArrayType(
@@ -2904,6 +2915,34 @@ QualType ASTContext::getAutoType(QualType DeducedType) const {
return QualType(AT, 0);
}
+/// getAtomicType - Return the uniqued reference to the atomic type for
+/// the given value type.
+QualType ASTContext::getAtomicType(QualType T) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ AtomicType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(AT, 0);
+
+ // If the atomic value type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getAtomicType(getCanonicalType(T));
+
+ // Get the new insert position for the node we care about.
+ AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+ }
+ AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
+ Types.push_back(New);
+ AtomicTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
/// getAutoDeductType - Get type pattern for deducing against 'auto'.
QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
@@ -5802,6 +5841,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return RHS;
return getBlockPointerType(ResultType);
}
+ case Type::Atomic:
+ {
+ // Merge two pointer types, while trying to preserve typedef info
+ QualType LHSValue = LHS->getAs<AtomicType>()->getValueType();
+ QualType RHSValue = RHS->getAs<AtomicType>()->getValueType();
+ if (Unqualified) {
+ LHSValue = LHSValue.getUnqualifiedType();
+ RHSValue = RHSValue.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
+ return RHS;
+ return getAtomicType(ResultType);
+ }
case Type::ConstantArray:
{
const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index e50dcbe4b0..e95d01a98f 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -810,7 +810,15 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
}
-
+
+ case Type::Atomic: {
+ if (!IsStructurallyEquivalent(Context,
+ cast<AtomicType>(T1)->getValueType(),
+ cast<AtomicType>(T2)->getValueType()))
+ return false;
+ break;
+ }
+
} // end switch
return true;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e94cb2d54b..41cfa6ad01 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -788,6 +788,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::Atomic:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
@@ -2111,6 +2112,13 @@ void CXXNameMangler::mangleType(const AutoType *T) {
mangleType(D);
}
+void CXXNameMangler::mangleType(const AtomicType *T) {
+ // <type> ::= U <source-name> <type> # vendor extended type qualifier
+ // (Until there's a standardized mangling...)
+ Out << "U7_Atomic";
+ mangleType(T->getValueType());
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index a5bfd7d318..e327d8b180 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1113,6 +1113,10 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T) {
llvm_unreachable("Don't know how to mangle AutoTypes yet!");
}
+void MicrosoftCXXNameMangler::mangleType(const AtomicType *T) {
+ llvm_unreachable("Don't know how to mangle AtomicTypes yet!");
+}
+
void MicrosoftMangleContext::mangleName(const NamedDecl *D,
raw_ostream &Out) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index a2c6954d75..60cb3fa33e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2113,6 +2113,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
return Cache::get(cast<ObjCObjectType>(T)->getBaseType());
case Type::ObjCObjectPointer:
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
+ case Type::Atomic:
+ return Cache::get(cast<AtomicType>(T)->getValueType());
}
llvm_unreachable("unhandled type class");
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 855cc02d9e..fb7b918ca2 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -123,6 +123,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
case Type::DependentTemplateSpecialization:
case Type::ObjCObject:
case Type::ObjCInterface:
+ case Type::Atomic:
CanPrefixQualifiers = true;
break;
@@ -581,6 +582,16 @@ void TypePrinter::printAuto(const AutoType *T, std::string &S) {
}
}
+void TypePrinter::printAtomic(const AtomicType *T, std::string &S) {
+ if (!S.empty())
+ S = ' ' + S;
+ std::string Str;
+ IncludeStrongLifetimeRAII Strong(Policy);
+ print(T->getValueType(), Str);
+
+ S = "_Atomic(" + Str + ")" + S;
+}
+
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
if (DC->isTranslationUnit()) return;
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 7bd6fc2fb0..eda73253b5 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1423,6 +1423,13 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
0, 0, Elements);
}
+llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
+ llvm::DIFile U) {
+ // Ignore the atomic wrapping
+ // FIXME: What is the correct representation?
+ return getOrCreateType(Ty->getValueType(), U);
+}
+
/// CreateEnumType - get enumeration type.
llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
llvm::DIFile Unit = getOrCreateFile(ED->getLocation());
@@ -1581,6 +1588,9 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
case Type::MemberPointer:
return CreateType(cast<MemberPointerType>(Ty), Unit);
+ case Type::Atomic:
+ return CreateType(cast<AtomicType>(Ty), Unit);
+
case Type::Attributed:
case Type::TemplateSpecialization:
case Type::Elaborated:
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 19d1ff388c..68b3985961 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -96,6 +96,7 @@ class CGDebugInfo {
llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);
llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
llvm::DIType CreateEnumType(const EnumDecl *ED);
llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile F);
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index a1105d2894..2ad1ed3930 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -404,6 +404,7 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
case Type::Vector:
case Type::ExtVector:
case Type::Complex:
+ case Type::Atomic:
// FIXME: GCC treats block pointers as fundamental types?!
case Type::BlockPointer:
// abi::__fundamental_type_info.
@@ -656,6 +657,10 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
case Type::MemberPointer:
BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
break;
+
+ case Type::Atomic:
+ // No fields, at least for the moment.
+ break;
}
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 12def6728f..2c6e7b0acd 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -87,6 +87,10 @@ bool CodeGenFunction::hasAggregateLLVMType(QualType type) {
case Type::ObjCObject:
case Type::ObjCInterface:
return true;
+
+ // In IRGen, atomic types are just the underlying type
+ case Type::Atomic:
+ return hasAggregateLLVMType(type->getAs<AtomicType>()->getValueType());
}
llvm_unreachable("unknown type kind!");
}
@@ -983,6 +987,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::FunctionNoProto:
type = cast<FunctionType>(ty)->getResultType();
break;
+
+ case Type::Atomic:
+ type = cast<AtomicType>(ty)->getValueType();
+ break;
}
} while (type->isVariablyModifiedType());
}
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 3032f820c6..61c1581798 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -548,6 +548,11 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(Ty));
break;
}
+
+ case Type::Atomic: {
+ ResultType = ConvertTypeForMem(cast<AtomicType>(Ty)->getValueType());
+ break;
+ }
}
assert(ResultType && "Didn't convert a type?");
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5e1a42dc07..82155e44fd 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2184,6 +2184,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___underlying_type:
ParseUnderlyingTypeSpecifier(DS);
+ continue;
+
+ case tok::kw__Atomic:
+ ParseAtomicSpecifier(DS);
+ continue;
// OpenCL qualifiers:
case tok::kw_private:
@@ -2460,6 +2465,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
ParseUnderlyingTypeSpecifier(DS);
return true;
+ case tok::kw__Atomic:
+ ParseAtomicSpecifier(DS);
+ return true;
+
// OpenCL qualifiers:
case tok::kw_private:
if (!getLang().OpenCL)
@@ -3219,6 +3228,10 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_private:
return getLang().OpenCL;
+
+ // C1x _Atomic()
+ case tok::kw__Atomic:
+ return true;
}
}
@@ -3338,6 +3351,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_decltype:
return true;
+ // C1x _Atomic()
+ case tok::kw__Atomic:
+ return true;
+
// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
case tok::less:
return getLang().ObjC1;
@@ -4504,6 +4521,47 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
Diag(StartLoc, DiagID) << PrevSpec;
}
+/// [C1X] atomic-specifier:
+/// _Atomic ( type-name )
+///
+void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
+ assert(Tok.is(tok::kw__Atomic) && "Not an atomic specifier");
+
+ SourceLocation StartLoc = ConsumeToken();
+ SourceLocation LParenLoc = Tok.getLocation();
+
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "_Atomic")) {
+ SkipUntil(tok::r_paren);
+ return;