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 13:11:26 PDT 2013


On Mar 28, 2013, at 12:50 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Thu, Mar 28, 2013 at 10:42 AM, John McCall <rjmccall at apple.com> wrote:
> 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;
> 
> 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:
> 
> Added: cfe/trunk/test/Parser/atomic.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/atomic.c?rev=178210&view=auto
> ==============================================================================
> --- cfe/trunk/test/Parser/atomic.c (added)
> +++ cfe/trunk/test/Parser/atomic.c Wed Mar 27 20:55:44 2013
> @@ -0,0 +1,35 @@
> +// RUN: %clang_cc1 -std=c11 %s -fsyntax-only -verify -pedantic
> [...]
> +typedef const int const_int;
> [...]
> +typedef const _Atomic(int) const_atomic_int;
> +typedef _Atomic const_int const_atomic_int;
> +typedef _Atomic(const_int) const_atomic_int; // expected-error {{_Atomic cannot be applied to qualified type 'const_int' (aka 'const int')}}
> 
> 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 6.7.2.4/3), but you can have _Atomic T for T a qualified type (C11 6.7.3/2).

Ah, I see your reasoning.  This is somewhat strange, but okay.

John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130328/bd884fec/attachment.html>


More information about the cfe-commits mailing list