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
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 055ed7c..3377799 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1063,6 +1063,11 @@
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 @@
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 @@
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 @@
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 e50dcbe..e95d01a 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -810,7 +810,15 @@
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 e94cb2d..41cfa6a 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -788,6 +788,7 @@
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 @@
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 a5bfd7d..e327d8b 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1113,6 +1113,10 @@
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 a2c6954..60cb3fa 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2113,6 +2113,8 @@
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 855cc02..fb7b918 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -123,6 +123,7 @@
case Type::DependentTemplateSpecialization:
case Type::ObjCObject:
case Type::ObjCInterface:
+ case Type::Atomic:
CanPrefixQualifiers = true;
break;
@@ -581,6 +582,16 @@
}
}
+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 7bd6fc2..eda7325 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1423,6 +1423,13 @@
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 @@
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 19d1ff3..68b3985 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -96,6 +96,7 @@
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 a1105d2..2ad1ed3 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -404,6 +404,7 @@
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 @@
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 12def67..2c6e7b0 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -87,6 +87,10 @@
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 @@
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 3032f82..61c1581 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -548,6 +548,11 @@
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 5e1a42d..82155e4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2184,6 +2184,11 @@
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 @@
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 @@
case tok::kw_private:
return getLang().OpenCL;
+
+ // C1x _Atomic()
+ case tok::kw__Atomic:
+ return true;
}
}
@@ -3338,6 +3351,10 @@
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 @@
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;
+ }
+
+ TypeResult Result = ParseTypeName();
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ // Match the ')'
+ SourceLocation RParenLoc;
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (RParenLoc.isInvalid())
+ return;
+
+ DS.setTypeofParensRange(SourceRange(LParenLoc, RParenLoc));
+ DS.SetRangeEnd(RParenLoc);
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
+ DiagID, Result.release()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+}
+
/// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
/// from TryAltiVecVectorToken.
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 210d179..0e7d288 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -719,6 +719,7 @@
case tok::kw___unaligned:
case tok::kw___vector:
case tok::kw___pixel:
+ case tok::kw__Atomic:
return TPResult::False();
default:
@@ -1033,6 +1034,10 @@
case tok::kw___underlying_type:
return TPResult::True();
+ // C1x _Atomic
+ case tok::kw__Atomic:
+ return TPResult::True();
+
default:
return TPResult::False();
}
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index d7732c7..3564f26 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -243,6 +243,7 @@
}
switch (DS.getTypeSpecType()) {
+ case TST_atomic:
case TST_auto:
case TST_bool:
case TST_char:
@@ -389,6 +390,7 @@
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
+ case DeclSpec::TST_atomic: return "_Atomic";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 718a19b..534cd48 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3011,7 +3011,8 @@
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
case DeclSpec::TST_decltype:
- case DeclSpec::TST_underlyingType: {
+ case DeclSpec::TST_underlyingType:
+ case DeclSpec::TST_atomic: {
// Grab the type from the parser.
TypeSourceInfo *TSI = 0;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4df525c..cd57dcf 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3419,6 +3419,7 @@
CheckPolymorphic(ReferenceTypeLoc)
CheckPolymorphic(MemberPointerTypeLoc)
CheckPolymorphic(BlockPointerTypeLoc)
+ CheckPolymorphic(AtomicTypeLoc)
/// Handle all the types we haven't given a more specific
/// implementation for above.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7721caf..ec71a4e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -342,6 +342,10 @@
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
+ // We can't do lvalue-to-rvalue on atomics yet.
+ if (T->getAs<AtomicType>())
+ return Owned(E);
+
// Create a load out of an ObjCProperty l-value, if necessary.
if (E->getObjectKind() == OK_ObjCProperty) {
ExprResult Res = ConvertPropertyForRValue(E);
@@ -5393,6 +5397,10 @@
LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
+ // We can't do assignment from/to atomics yet.
+ if (LHSType->isAtomicType())
+ return Incompatible;
+
// Common case: no conversion required.
if (LHSType == RHSType) {
Kind = CK_NoOp;
@@ -5712,7 +5720,7 @@
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
bool Diagnose) {
if (getLangOptions().CPlusPlus) {
- if (!LHSType->isRecordType()) {
+ if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
@@ -5732,6 +5740,8 @@
// FIXME: Currently, we fall through and treat C++ classes like C
// structures.
+ // FIXME: We also fall through for atomics; not sure what should
+ // happen there, though.
}
// C99 6.5.16.1p1: the left operand is a pointer and the right is
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 84ae42a..75da41d 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -2000,6 +2000,12 @@
case Type::ObjCObjectPointer:
Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl());
break;
+
+ // Atomic types are just wrappers; use the associations of the
+ // contained type.
+ case Type::Atomic:
+ T = cast<AtomicType>(T)->getValueType().getTypePtr();
+ continue;
}
if (Queue.empty()) break;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index c8cf6c4..cd1092a 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3246,6 +3246,10 @@
return false;
}
+bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
+ return Visit(T->getValueType());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
S.Diag(SR.getBegin(), diag::ext_template_arg_local_type)
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5d5cdc5..70fdf64 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1116,7 +1116,17 @@
Info, Deduced, TDF);
return Sema::TDK_NonDeducedMismatch;
-
+
+ // _Atomic T [extension]
+ case Type::Atomic:
+ if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>())
+ return DeduceTemplateArguments(S, TemplateParams,
+ cast<AtomicType>(Param)->getValueType(),
+ AtomicArg->getValueType(),
+ Info, Deduced, TDF);
+
+ return Sema::TDK_NonDeducedMismatch;
+
// T *
case Type::Pointer: {
QualType PointeeType;
@@ -4126,6 +4136,13 @@
OnlyDeduced, Depth, Used);
break;
+ case Type::Atomic:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<AtomicType>(T)->getValueType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
case Type::DependentName:
if (!OnlyDeduced)
MarkUsedTemplateParameters(SemaRef,
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 2b7250f..a2aa1b3 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -619,7 +619,8 @@
switch (DS.getTypeSpecType()) {
case TST_typename:
case TST_typeofType:
- case TST_underlyingType: {
+ case TST_underlyingType:
+ case TST_atomic: {
QualType T = DS.getRepAsType().get();
if (!T.isNull() && T->containsUnexpandedParameterPack())
return true;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 4a865bf..995d767 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -856,6 +856,16 @@
Result = Context.UnknownAnyTy;
break;
+ case DeclSpec::TST_atomic:
+ Result = S.GetTypeFromParser(DS.getRepAsType());
+ assert(!Result.isNull() && "Didn't get a type for _Atomic?");
+ Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ }
+ break;
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -2872,6 +2882,10 @@
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
+ void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
+ }
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
@@ -4183,3 +4197,36 @@
}
llvm_unreachable("unknown unary transform type");
}
+
+QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
+ if (!T->isDependentType()) {
+ int DisallowedKind = -1;
+ if (T->isIncompleteType())
+ // FIXME: It isn't entirely clear whether incomplete atomic types
+ // are allowed or not; for simplicity, ban them for the moment.
+ DisallowedKind = 0;
+ else if (T->isArrayType())
+ DisallowedKind = 1;
+ else if (T->isFunctionType())
+ DisallowedKind = 2;
+ else if (T->isReferenceType())
+ DisallowedKind = 3;
+ else if (T->isAtomicType())
+ DisallowedKind = 4;
+ else if (T.hasQualifiers())
+ DisallowedKind = 5;
+ else if (!T.isTriviallyCopyableType(Context))
+ // Some other non-trivially-copyable type (probably a C++ class)
+ DisallowedKind = 6;
+
+ if (DisallowedKind != -1) {
+ Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
+ return QualType();
+ }
+
+ // FIXME: Do we need any handling for ARC here?
+ }
+
+ // Build the pointer type.
+ return Context.getAtomicType(T);
+}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 62c6d18..33aaf92 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -905,6 +905,12 @@
NumExpansions);
}
+ /// \brief Build a new atomic type given its value type.
+ ///
+ /// By default, performs semantic analysis when building the atomic type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
+
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
@@ -4399,6 +4405,29 @@
return getDerived().TransformTemplateSpecializationType(TLB, TL, Template);
}
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
+ AtomicTypeLoc TL) {
+ QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc());
+ if (ValueType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ValueType != TL.getValueLoc().getType()) {
+ Result = getDerived().RebuildAtomicType(ValueType, TL.getKWLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ AtomicTypeLoc NewTL = TLB.push<AtomicTypeLoc>(Result);
+ NewTL.setKWLoc(TL.getKWLoc());
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+
+ return Result;
+}
+
namespace {
/// \brief Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
@@ -8277,6 +8306,12 @@
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
+ SourceLocation KWLoc) {
+ return SemaRef.BuildAtomicType(ValueType, KWLoc);
+}
+
+template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index cda7d2c..361c3b7 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3526,6 +3526,15 @@
const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
return T;
}
+
+ case TYPE_ATOMIC: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of atomic type");
+ return QualType();
+ }
+ QualType ValueType = readType(*Loc.F, Record, Idx);
+ return Context.getAtomicType(ValueType);
+ }
}
// Suppress a GCC warning
return QualType();
@@ -3760,6 +3769,11 @@
void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
TL.setStarLoc(ReadSourceLocation(Record, Idx));
}
+void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ TL.setKWLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
TypeSourceInfo *ASTReader::GetTypeSourceInfo(Module &F,
const RecordData &Record,
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 9b534c9..e648c7c 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -388,6 +388,12 @@
Code = TYPE_OBJC_OBJECT_POINTER;
}
+void
+ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
+ Writer.AddTypeRef(T->getValueType(), Record);
+ Code = TYPE_ATOMIC;
+}
+
namespace {
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
@@ -596,6 +602,11 @@
void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getStarLoc(), Record);
}
+void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKWLoc(), Record);
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+}
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
@@ -840,6 +851,7 @@
RECORD(TYPE_PACK_EXPANSION);
RECORD(TYPE_ATTRIBUTED);
RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
+ RECORD(TYPE_ATOMIC);
RECORD(DECL_TYPEDEF);
RECORD(DECL_ENUM);
RECORD(DECL_RECORD);