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