diff options
Diffstat (limited to 'clang/lib')
25 files changed, 337 insertions, 5 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 055ed7c08c6..3377799e3dd 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index e50dcbe4b00..e95d01a98fb 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index e94cb2d54bc..41cfa6ad01e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/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/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index a5bfd7d318e..e327d8b180a 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a2c6954d751..60cb3fa33e5 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/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/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 855cc02d9e6..fb7b918ca2f 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/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/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 7bd6fc2fb00..eda73253b56 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/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/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 19d1ff388cd..68b3985961e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/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/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index a1105d28940..2ad1ed39303 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 12def6728f5..2c6e7b0acdd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 3032f820c66..61c15817982 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5e1a42dc073..82155e44fdc 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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; + } + + 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/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 210d179db1f..0e7d288395e 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -719,6 +719,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___unaligned: case tok::kw___vector: case tok::kw___pixel: + case tok::kw__Atomic: return TPResult::False(); default: @@ -1033,6 +1034,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___underlying_type: return TPResult::True(); + // C1x _Atomic + case tok::kw__Atomic: + return TPResult::True(); + default: return TPResult::False(); } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d7732c78ddb..3564f2657b0 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -243,6 +243,7 @@ bool Declarator::isDeclarationOfFunction() const { } switch (DS.getTypeSpecType()) { + case TST_atomic: case TST_auto: case TST_bool: case TST_char: @@ -389,6 +390,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { 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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 718a19b9880..534cd488e75 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3011,7 +3011,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, 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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4df525c6f3c..cd57dcfb9a3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3419,6 +3419,7 @@ struct CheckAbstractUsage { 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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7721caf9397..ec71a4e94d1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -342,6 +342,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { 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 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, 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::AssignConvertType 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 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, // 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/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 84ae42a9b95..75da41dd770 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2000,6 +2000,12 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { 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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c8cf6c4c2c9..cd1092a9bcc 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3246,6 +3246,10 @@ bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType( 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/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 5d5cdc52335..70fdf64e7ca 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1116,7 +1116,17 @@ DeduceTemplateArguments(Sema &S, 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 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, 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/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 2b7250f1a2b..a2aa1b30264 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -619,7 +619,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { 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/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 4a865bf2358..995d767e2be 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -856,6 +856,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { 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 @@ namespace { 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 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType, } 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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 62c6d18b59f..33aaf92d813 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -905,6 +905,12 @@ public: 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 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( 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 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( } 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/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index cda7d2cc2a2..361c3b79ca7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3526,6 +3526,15 @@ QualType ASTReader::readTypeRecord(unsigned Index) { 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::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { 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/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 9b534c91654..e648c7cd5d9 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -388,6 +388,12 @@ ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { 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::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { 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 @@ void ASTWriter::WriteBlockInfoBlock() { 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); |