diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-10-06 23:00:33 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-10-06 23:00:33 +0000 |
commit | b001de7458d17c17e6d8b8034c7cfcefd3b70c00 (patch) | |
tree | 22aafdcc75a1bc4984c7112800b87ece9b2f54c6 /lib/Sema | |
parent | 5f22614327065a4ae78588eda8cb62f8b50502aa (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
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 47 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 35 |
10 files changed, 128 insertions, 4 deletions
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index d7732c78dd..3564f2657b 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 718a19b988..534cd488e7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4df525c6f3..cd57dcfb9a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7721caf939..ec71a4e94d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 84ae42a9b9..75da41dd77 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/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/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c8cf6c4c2c..cd1092a9bc 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 5d5cdc5233..70fdf64e7c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/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/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 2b7250f1a2..a2aa1b3026 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 4a865bf235..995d767e2b 100644 --- a/lib/Sema/SemaType.cpp +++ b/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/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 62c6d18b59..33aaf92d81 100644 --- a/lib/Sema/TreeTransform.h +++ b/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, |