r178210 - Support C11 _Atomic type qualifier. This is more-or-less just syntactic sugar for the _Atomic type specifier.
John McCall
rjmccall at apple.com
Thu Mar 28 10:42:55 PDT 2013
On Mar 27, 2013, at 6:55 PM, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> Author: rsmith
> Date: Wed Mar 27 20:55:44 2013
> New Revision: 178210
>
> URL: http://llvm.org/viewvc/llvm-project?rev=178210&view=rev
> Log:
> Support C11 _Atomic type qualifier. This is more-or-less just syntactic sugar for the _Atomic type specifier.
>
> Added:
> cfe/trunk/test/Parser/atomic.c
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Parse/Parser.h
> cfe/trunk/include/clang/Sema/DeclSpec.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/lib/Parse/ParseDecl.cpp
> cfe/trunk/lib/Parse/ParseStmt.cpp
> cfe/trunk/lib/Sema/DeclSpec.cpp
> cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaType.cpp
> cfe/trunk/test/Parser/asm.c
> cfe/trunk/test/SemaCXX/atomic-type.cxx
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 27 20:55:44 2013
> @@ -1166,8 +1166,7 @@ def warn_cxx98_compat_static_data_member
> def err_union_member_of_reference_type : Error<
> "union member %0 has reference type %1">;
> def ext_anonymous_struct_union_qualified : Extension<
> - "anonymous %select{struct|union}0 cannot be '%select{const|volatile|"
> - "restrict}1'">;
> + "anonymous %select{struct|union}0 cannot be '%1'">;
> def err_different_return_type_for_overriding_virtual_function : Error<
> "virtual function %0 has a different return type "
> "%diff{($) than the function it overrides (which has return type $)|"
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Wed Mar 27 20:55:44 2013
> @@ -1999,7 +1999,8 @@ private:
> DirectDeclParseFunction DirectDeclParser);
>
> void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
> - bool CXX11AttributesAllowed = true);
> + bool CXX11AttributesAllowed = true,
> + bool AtomicAllowed = true);
> void ParseDirectDeclarator(Declarator &D);
> void ParseParenDeclarator(Declarator &D);
> void ParseFunctionDeclarator(Declarator &D,
>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Mar 27 20:55:44 2013
> @@ -291,7 +291,10 @@ public:
> TQ_unspecified = 0,
> TQ_const = 1,
> TQ_restrict = 2,
> - TQ_volatile = 4
> + TQ_volatile = 4,
> + // This has no corresponding Qualifiers::TQ value, because it's not treated
> + // as a qualifier in our type system.
> + TQ_atomic = 8
> };
>
> /// ParsedSpecifiers - Flags to query which specifiers were applied. This is
> @@ -321,7 +324,7 @@ private:
> unsigned TypeSpecOwned : 1;
>
> // type-qualifiers
> - unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
> + unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
>
> // function-specifier
> unsigned FS_inline_specified : 1;
> @@ -369,7 +372,7 @@ private:
> /// TSTNameLoc provides source range info for tag types.
> SourceLocation TSTNameLoc;
> SourceRange TypeofParensRange;
> - SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
> + SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc;
> SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
> SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
>
> @@ -503,6 +506,7 @@ public:
> SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
> SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
> SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
> + SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
>
> /// \brief Clear out all of the type qualifiers.
> void ClearTypeQualifiers() {
> @@ -510,6 +514,7 @@ public:
> TQ_constLoc = SourceLocation();
> TQ_restrictLoc = SourceLocation();
> TQ_volatileLoc = SourceLocation();
> + TQ_atomicLoc = SourceLocation();
> }
>
> // function-specifier
> @@ -1025,8 +1030,8 @@ struct DeclaratorChunk {
> };
>
> struct PointerTypeInfo : TypeInfoCommon {
> - /// The type qualifiers: const/volatile/restrict.
> - unsigned TypeQuals : 3;
> + /// The type qualifiers: const/volatile/restrict/atomic.
> + unsigned TypeQuals : 4;
>
> /// The location of the const-qualifier, if any.
> unsigned ConstQualLoc;
> @@ -1037,6 +1042,9 @@ struct DeclaratorChunk {
> /// The location of the restrict-qualifier, if any.
> unsigned RestrictQualLoc;
>
> + /// The location of the _Atomic-qualifier, if any.
> + unsigned AtomicQualLoc;
> +
> void destroy() {
> }
> };
> @@ -1051,8 +1059,8 @@ struct DeclaratorChunk {
> };
>
> struct ArrayTypeInfo : TypeInfoCommon {
> - /// The type qualifiers for the array: const/volatile/restrict.
> - unsigned TypeQuals : 3;
> + /// The type qualifiers for the array: const/volatile/restrict/_Atomic.
> + unsigned TypeQuals : 4;
>
> /// True if this dimension included the 'static' keyword.
> bool hasStatic : 1;
> @@ -1274,16 +1282,16 @@ struct DeclaratorChunk {
>
> struct BlockPointerTypeInfo : TypeInfoCommon {
> /// For now, sema will catch these as invalid.
> - /// The type qualifiers: const/volatile/restrict.
> - unsigned TypeQuals : 3;
> + /// The type qualifiers: const/volatile/restrict/_Atomic.
> + unsigned TypeQuals : 4;
>
> void destroy() {
> }
> };
>
> struct MemberPointerTypeInfo : TypeInfoCommon {
> - /// The type qualifiers: const/volatile/restrict.
> - unsigned TypeQuals : 3;
> + /// The type qualifiers: const/volatile/restrict/_Atomic.
> + unsigned TypeQuals : 4;
> // CXXScopeSpec has a constructor, so it can't be a direct member.
> // So we need some pointer-aligned storage and a bit of trickery.
> union {
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 27 20:55:44 2013
> @@ -936,10 +936,8 @@ public:
>
> QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
> const DeclSpec *DS = 0);
> - QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR,
> - const DeclSpec *DS = 0) {
> - return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS);
> - }
> + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA,
> + const DeclSpec *DS = 0);
> QualType BuildPointerType(QualType T,
> SourceLocation Loc, DeclarationName Entity);
> QualType BuildReferenceType(QualType T, bool LValueRef,
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Mar 27 20:55:44 2013
> @@ -2905,8 +2905,17 @@ void Parser::ParseDeclarationSpecifiers(
> continue;
>
> case tok::kw__Atomic:
> - ParseAtomicSpecifier(DS);
> - continue;
> + // C11 6.7.2.4/4:
> + // If the _Atomic keyword is immediately followed by a left parenthesis,
> + // it is interpreted as a type specifier (with a type name), not as a
> + // type qualifier.
> + if (NextToken().is(tok::l_paren)) {
> + ParseAtomicSpecifier(DS);
> + continue;
> + }
> + isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
> + getLangOpts());
> + break;
>
> // OpenCL qualifiers:
> case tok::kw_private:
> @@ -3814,7 +3823,7 @@ bool Parser::isTypeSpecifierQualifier()
> case tok::kw_private:
> return getLangOpts().OpenCL;
>
> - // C11 _Atomic()
> + // C11 _Atomic
> case tok::kw__Atomic:
> return true;
> }
> @@ -3959,7 +3968,7 @@ bool Parser::isDeclarationSpecifier(bool
> case tok::annot_decltype:
> case tok::kw_constexpr:
>
> - // C11 _Atomic()
> + // C11 _Atomic
> case tok::kw__Atomic:
> return true;
>
> @@ -4099,7 +4108,8 @@ bool Parser::isConstructorDeclarator() {
> ///
> void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
> bool VendorAttributesAllowed,
> - bool CXX11AttributesAllowed) {
> + bool CXX11AttributesAllowed,
> + bool AtomicAllowed) {
> if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed &&
> isCXX11AttributeSpecifier()) {
> ParsedAttributesWithRange attrs(AttrFactory);
> @@ -4132,6 +4142,12 @@ void Parser::ParseTypeQualifierListOpt(D
> isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
> getLangOpts());
> break;
> + case tok::kw__Atomic:
> + if (!AtomicAllowed)
> + goto DoneWithTypeQuals;
> + isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
> + getLangOpts());
> + break;
>
> // OpenCL qualifiers:
> case tok::kw_private:
> @@ -4346,6 +4362,10 @@ void Parser::ParseDeclaratorInternal(Dec
> if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
> Diag(DS.getVolatileSpecLoc(),
> diag::err_invalid_reference_qualifier_application) << "volatile";
> + // 'restrict' is permitted as an extension.
> + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
> + Diag(DS.getAtomicSpecLoc(),
> + diag::err_invalid_reference_qualifier_application) << "_Atomic";
> }
>
> // Recursively parse the declarator.
> @@ -4368,7 +4388,7 @@ void Parser::ParseDeclaratorInternal(Dec
> }
> }
>
> - // Remember that we parsed a reference type. It doesn't have type-quals.
> + // Remember that we parsed a reference type.
> D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
> Kind == tok::amp),
> DS.getAttributes(),
> @@ -4809,7 +4829,9 @@ void Parser::ParseFunctionDeclarator(Dec
> // with the virt-specifier-seq and pure-specifier in the same way.
>
> // Parse cv-qualifier-seq[opt].
> - ParseTypeQualifierListOpt(DS, false /*no attributes*/, false);
> + ParseTypeQualifierListOpt(DS, /*VendorAttributesAllowed*/ false,
> + /*CXX11AttributesAllowed*/ false,
> + /*AtomicAllowed*/ false);
> if (!DS.getSourceRange().getEnd().isInvalid()) {
> EndLoc = DS.getSourceRange().getEnd();
> ConstQualifierLoc = DS.getConstSpecLoc();
> @@ -5350,14 +5372,13 @@ void Parser::ParseTypeofSpecifier(DeclSp
> /// _Atomic ( type-name )
> ///
> void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
> - assert(Tok.is(tok::kw__Atomic) && "Not an atomic specifier");
> + assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) &&
> + "Not an atomic specifier");
>
> SourceLocation StartLoc = ConsumeToken();
> BalancedDelimiterTracker T(*this, tok::l_paren);
> - if (T.expectAndConsume(diag::err_expected_lparen_after, "_Atomic")) {
> - SkipUntil(tok::r_paren);
> + if (T.consumeOpen())
> return;
> - }
>
> TypeResult Result = ParseTypeName();
> if (Result.isInvalid()) {
>
> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Wed Mar 27 20:55:44 2013
> @@ -1810,6 +1810,9 @@ StmtResult Parser::ParseAsmStatement(boo
> Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
> if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
> Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
> + // FIXME: Once GCC supports _Atomic, check whether it permits it here.
> + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
> + Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
>
> // Remember if this was a volatile asm.
> bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
>
> Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/DeclSpec.cpp Wed Mar 27 20:55:44 2013
> @@ -169,6 +169,9 @@ DeclaratorChunk DeclaratorChunk::getFunc
> SourceLocation LocalRangeEnd,
> Declarator &TheDeclarator,
> TypeResult TrailingReturnType) {
> + assert(!(TypeQuals & DeclSpec::TQ_atomic) &&
> + "function cannot have _Atomic qualifier");
> +
> DeclaratorChunk I;
> I.Kind = Function;
> I.Loc = LocalRangeBegin;
> @@ -442,6 +445,7 @@ const char *DeclSpec::getSpecifierName(T
> case DeclSpec::TQ_const: return "const";
> case DeclSpec::TQ_restrict: return "restrict";
> case DeclSpec::TQ_volatile: return "volatile";
> + case DeclSpec::TQ_atomic: return "_Atomic";
> }
> llvm_unreachable("Unknown typespec!");
> }
> @@ -710,12 +714,14 @@ bool DeclSpec::SetTypeQual(TQ T, SourceL
> TypeQualifiers |= T;
>
> switch (T) {
> - default: llvm_unreachable("Unknown type qualifier!");
> - case TQ_const: TQ_constLoc = Loc; break;
> - case TQ_restrict: TQ_restrictLoc = Loc; break;
> - case TQ_volatile: TQ_volatileLoc = Loc; break;
> + case TQ_unspecified: break;
> + case TQ_const: TQ_constLoc = Loc; return false;
> + case TQ_restrict: TQ_restrictLoc = Loc; return false;
> + case TQ_volatile: TQ_volatileLoc = Loc; return false;
> + case TQ_atomic: TQ_atomicLoc = Loc; return false;
> }
> - return false;
> +
> + llvm_unreachable("Unknown type qualifier!");
> }
>
> bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) {
>
> Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Mar 27 20:55:44 2013
> @@ -3729,6 +3729,9 @@ void Sema::CodeCompleteTypeQualifiers(De
> if (getLangOpts().C99 &&
> !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
> Results.AddResult("restrict");
> + if (getLangOpts().C11 &&
> + !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
> + Results.AddResult("_Atomic");
> Results.ExitScope();
> HandleCodeCompleteResults(this, CodeCompleter,
> Results.getCompletionContext(),
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 27 20:55:44 2013
> @@ -3175,6 +3175,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(S
> if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
> Diag(DS.getConstSpecLoc(), DiagID) << "volatile";
> // Restrict is covered above.
> + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
> + Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic";
> }
>
> // Warn about ignored type attributes, for example:
> @@ -3411,18 +3413,23 @@ Decl *Sema::BuildAnonymousStructOrUnion(
> if (DS.getTypeQualifiers()) {
> if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
> Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
> - << Record->isUnion() << 0
> + << Record->isUnion() << "const"
> << FixItHint::CreateRemoval(DS.getConstSpecLoc());
> if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
> - Diag(DS.getVolatileSpecLoc(),
> + Diag(DS.getVolatileSpecLoc(),
> diag::ext_anonymous_struct_union_qualified)
> - << Record->isUnion() << 1
> + << Record->isUnion() << "volatile"
> << FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
> if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
> - Diag(DS.getRestrictSpecLoc(),
> + Diag(DS.getRestrictSpecLoc(),
> diag::ext_anonymous_struct_union_qualified)
> - << Record->isUnion() << 2
> + << Record->isUnion() << "restrict"
> << FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
> + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
> + Diag(DS.getAtomicSpecLoc(),
> + diag::ext_anonymous_struct_union_qualified)
> + << Record->isUnion() << "_Atomic"
> + << FixItHint::CreateRemoval(DS.getAtomicSpecLoc());
>
> DS.ClearTypeQualifiers();
> }
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=178210&r1=178209&r2=178210&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Mar 27 20:55:44 2013
> @@ -1089,21 +1089,18 @@ static QualType ConvertDeclSpecToType(Ty
> // of a function type includes any type qualifiers, the behavior is
> // undefined."
> if (Result->isFunctionType() && TypeQuals) {
> - // Get some location to point at, either the C or V location.
> - SourceLocation Loc;
> if (TypeQuals & DeclSpec::TQ_const)
> - Loc = DS.getConstSpecLoc();
> + S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
> + << Result << DS.getSourceRange();
> else if (TypeQuals & DeclSpec::TQ_volatile)
> - Loc = DS.getVolatileSpecLoc();
> + S.Diag(DS.getVolatileSpecLoc(), diag::warn_typecheck_function_qualifiers)
> + << Result << DS.getSourceRange();
> else {
> - assert((TypeQuals & DeclSpec::TQ_restrict) &&
> - "Has CVR quals but not C, V, or R?");
> - // No diagnostic; we'll diagnose 'restrict' applied to a function type
> - // later, in BuildQualifiedType.
> + assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
> + "Has CVRA quals but not C, V, R, or A?");
> + // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a
> + // function type later, in BuildQualifiedType.
> }
> - if (!Loc.isInvalid())
> - S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
> - << Result << DS.getSourceRange();
> }
>
> // C++ [dcl.ref]p1:
> @@ -1116,6 +1113,7 @@ static QualType ConvertDeclSpecToType(Ty
> TypeQuals && Result->isReferenceType()) {
> TypeQuals &= ~DeclSpec::TQ_const;
> TypeQuals &= ~DeclSpec::TQ_volatile;
> + TypeQuals &= ~DeclSpec::TQ_atomic;
> }
>
> // C90 6.5.3 constraints: "The same type qualifier shall not appear more
> @@ -1133,11 +1131,17 @@ static QualType ConvertDeclSpecToType(Ty
> << "volatile";
> }
>
> - // C90 doesn't have restrict, so it doesn't force us to produce a warning
> - // in this case.
> + // C90 doesn't have restrict nor _Atomic, so it doesn't force us to
> + // produce a warning in this case.
> }
>
> - return S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
> + QualType Qualified = S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
> +
> + // If adding qualifiers fails, just use the unqualified type.
> + if (Qualified.isNull())
> + declarator.setInvalidType(true);
> + else
> + Result = Qualified;
> }
>
> return Result;
> @@ -1188,6 +1192,39 @@ QualType Sema::BuildQualifiedType(QualTy
> return Context.getQualifiedType(T, Qs);
> }
>
> +QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
> + unsigned CVRA, const DeclSpec *DS) {
> + // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic.
> + unsigned CVR = CVRA & ~DeclSpec::TQ_atomic;
> +
> + // C11 6.7.3/5:
> + // If the same qualifier appears more than once in the same
> + // specifier-qualifier-list, either directly or via one or more typedefs,
> + // the behavior is the same as if it appeared only once.
> + //
> + // It's not specified what happens when the _Atomic qualifier is applied to
> + // a type specified with the _Atomic specifier, but we assume that this
> + // should be treated as if the _Atomic qualifier appeared multiple times.
> + if (CVRA & DeclSpec::TQ_atomic && !T->isAtomicType()) {
> + // C11 6.7.3/5:
> + // If other qualifiers appear along with the _Atomic qualifier in a
> + // specifier-qualifier-list, the resulting type is the so-qualified
> + // atomic type.
> + //
> + // Don't need to worry about array types here, since _Atomic can't be
> + // applied to such types.
> + SplitQualType Split = T.getSplitUnqualifiedType();
> + T = BuildAtomicType(QualType(Split.Ty, 0),
> + DS ? DS->getAtomicSpecLoc() : Loc);
Won't this silently reinterpret the following so that 'x' has type
'const _Atomic(int)'? Are you sure that's intended behavior?
typedef const int cint;
_Atomic cint x;
John.
More information about the cfe-commits
mailing list