diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-08 00:56:48 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-01-08 00:56:48 +0000 |
commit | 649c7b069f53596e2c651d6524cf7c6621e3d565 (patch) | |
tree | 843dea1c8f456052afad31c30fa10dcf7f0eb6b1 /clang/lib | |
parent | 1c3996abc7201af3e2041527a3e1fb3d4d4774c1 (diff) | |
download | bcm5719-llvm-649c7b069f53596e2c651d6524cf7c6621e3d565.tar.gz bcm5719-llvm-649c7b069f53596e2c651d6524cf7c6621e3d565.zip |
PR18234: Mark a tag definition as invalid early if it appears in a
type-specifier in C++. Some checks will assert in this case otherwise (in
particular, the access specifier may be missing if this happens inside a class
definition, due to a violation of an AST invariant).
llvm-svn: 198721
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 3 |
5 files changed, 33 insertions, 16 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 277355cd40d..27df0c0795d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2056,8 +2056,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); - if ((DSC == DSC_type_specifier || DSC == DSC_trailing) && - !DS.hasTypeSpecifier()) { + if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) { Diag(Tok, diag::err_expected_type); DS.SetTypeSpecError(); } else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() && @@ -2155,8 +2154,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // within a type specifier. Outside of C++, we allow this even if the // language doesn't "officially" support implicit int -- we support // implicit int as an extension in C99 and C11. - if (DSC != DSC_type_specifier && DSC != DSC_trailing && - !getLangOpts().CPlusPlus && + if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus && isValidAfterIdentifierInDeclarator(NextToken())) { // If this token is valid for implicit int, e.g. "static x = 4", then // we just avoid eating the identifier, so it will be parsed as the @@ -2226,7 +2224,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // Determine whether this identifier could plausibly be the name of something // being declared (with a missing type). - if (DSC != DSC_type_specifier && DSC != DSC_trailing && + if (!isTypeSpecifier(DSC) && (!SS || DSC == DSC_top_level || DSC == DSC_class)) { // Look ahead to the next token to try to figure out what this declaration // was supposed to be. @@ -2339,6 +2337,9 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { return DSC_top_level; if (Context == Declarator::TrailingReturnContext) return DSC_trailing; + if (Context == Declarator::AliasDeclContext || + Context == Declarator::AliasTemplateContext) + return DSC_alias_declaration; return DSC_normal; } @@ -3751,7 +3752,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } else { TUK = Sema::TUK_Definition; } - } else if (DSC != DSC_type_specifier && + } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(CanBeBitfield)))) { @@ -3813,7 +3814,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, StartLoc, SS, Name, NameLoc, attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, - IsScopedUsingClassTag, BaseType); + IsScopedUsingClassTag, BaseType, + DSC == DSC_type_specifier); if (IsDependent) { // This enum has a dependent nested-name-specifier. Handle it as a diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 295ade33572..1fbc0adeb93 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1308,7 +1308,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // new struct s; // or // &T::operator struct s; - // For these, DSC is DSC_type_specifier. + // For these, DSC is DSC_type_specifier or DSC_alias_declaration. // If there are attributes after class name, parse them. MaybeParseCXX11Attributes(Attributes); @@ -1365,7 +1365,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TUK = Sema::TUK_Reference; PA.Revert(); - } else if (DSC != DSC_type_specifier && + } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; @@ -1581,7 +1581,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, - clang::TypeResult()); + clang::TypeResult(), + DSC == DSC_type_specifier); // If ActOnTag said the type was dependent, try again with the // less common call. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 07a551da2f1..7cdf81a87e4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10396,6 +10396,9 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. +/// +/// IsTypeSpecifier is true if this is a type-specifier (or +/// trailing-type-specifier) other than one in an alias-declaration. Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -10405,7 +10408,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType) { + TypeResult UnderlyingType, + bool IsTypeSpecifier) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != 0 || TUK == TUK_Definition) && @@ -11016,6 +11020,14 @@ CreateNewDecl: cast_or_null<RecordDecl>(PrevDecl)); } + // C++11 [dcl.type]p3: + // A type-specifier-seq shall not define a class or enumeration [...]. + if (getLangOpts().CPlusPlus && IsTypeSpecifier && TUK == TUK_Definition) { + Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) + << Context.getTagDeclType(New); + Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 91b9c6a5880..28f038a69e3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11460,14 +11460,15 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, bool Owned = false; bool IsDependent = false; return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, - Attr, AS_public, + Attr, AS_public, /*ModulePrivateLoc=*/SourceLocation(), - MultiTemplateParamsArg(), Owned, IsDependent, + MultiTemplateParamsArg(), Owned, IsDependent, /*ScopedEnumKWLoc=*/SourceLocation(), /*ScopedEnumUsesClassTag=*/false, - /*UnderlyingType=*/TypeResult()); + /*UnderlyingType=*/TypeResult(), + /*IsTypeSpecifier=*/false); } - + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4f050345bc8..b468e31f097 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7101,7 +7101,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, KWLoc, SS, Name, NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, - SourceLocation(), false, TypeResult()); + SourceLocation(), false, TypeResult(), + /*IsTypeSpecifier*/false); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) |