From: Richard Smith Date: Fri, 1 Jul 2011 19:46:12 +0000 (+0000) Subject: Fix AST representations of alias-declarations which define tag types. Inside classes... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c89edf5aaa08683f4afcf61a7a1d183c08b76498;p=clang Fix AST representations of alias-declarations which define tag types. Inside classes, the tag types need to have an associated access specifier, and inside function definitions, they need to be included in the declarations of the DeclStmt. These issues manifested as assertions during template instantiation, and also in a WIP constexpr patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134250 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 0b0946c010..626ad5316d 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1450,7 +1450,7 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), bool SuppressDeclarations = false); - void ParseSpecifierQualifierList(DeclSpec &DS); + void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none); void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, ObjCTypeNameContext Context); @@ -1628,7 +1628,9 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context = Declarator::TypeNameContext, - ObjCDeclSpec *objcQuals = 0); + ObjCDeclSpec *objcQuals = 0, + AccessSpecifier AS = AS_none, + Decl **OwnedType = 0); void ParseBlockId(); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { @@ -1778,7 +1780,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, Decl *ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs); + ParsedAttributesWithRange &attrs, + Decl **OwnedType = 0); Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, @@ -1787,7 +1790,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none); + AccessSpecifier AS = AS_none, + Decl **OwnedType = 0); Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd); Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 65ce34a7a2..118130f8d9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -839,7 +839,7 @@ public: // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // - DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr); + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = 0); void DiagnoseUseOfUnimplementedSelectors(); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 99441e0e0e..3b08469ca1 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -32,11 +32,15 @@ using namespace clang; /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context, - ObjCDeclSpec *objcQuals) { + ObjCDeclSpec *objcQuals, + AccessSpecifier AS, + Decl **OwnedType) { // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); DS.setObjCQualifiers(objcQuals); - ParseSpecifierQualifierList(DS); + ParseSpecifierQualifierList(DS, AS); + if (OwnedType) + *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; // Parse the abstract-declarator, if present. Declarator DeclaratorInfo(DS, Context); @@ -674,6 +678,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, ParenBraceBracketBalancer BalancerRAIIObj(*this); Decl *SingleDecl = 0; + Decl *OwnedType = 0; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: @@ -696,7 +701,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, break; case tok::kw_using: SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs); + DeclEnd, attrs, &OwnedType); break; case tok::kw_static_assert: case tok::kw__Static_assert: @@ -708,8 +713,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, } // This routine returns a DeclGroup, if the thing we parsed only contains a - // single decl, convert it now. - return Actions.ConvertDeclToDeclGroup(SingleDecl); + // single decl, convert it now. Alias declarations can also declare a type; + // include that too if it is present. + return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] @@ -1081,10 +1087,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, /// type-qualifier specifier-qualifier-list[opt] /// [GNU] attributes specifier-qualifier-list[opt] /// -void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { +void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS) { /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. - ParseDeclarationSpecifiers(DS); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index b123461f1d..d78f3728e1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -314,7 +314,8 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs) { + ParsedAttributesWithRange &attrs, + Decl **OwnedType) { assert(Tok.is(tok::kw_using) && "Not using token"); // Eat 'using'. @@ -342,7 +343,8 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, // Using declarations can't have attributes. ProhibitAttributes(attrs); - return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd); + return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, + AS_none, OwnedType); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -422,7 +424,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, - AccessSpecifier AS) { + AccessSpecifier AS, + Decl **OwnedType) { CXXScopeSpec SS; SourceLocation TypenameLoc; bool IsTypeName; @@ -511,7 +514,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? Declarator::AliasTemplateContext : - Declarator::AliasDeclContext); + Declarator::AliasDeclContext, 0, AS, OwnedType); } else // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(attrs); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8069eb4385..ad1a62eb7f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -45,7 +45,12 @@ using namespace clang; using namespace sema; -Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { + if (OwnedType) { + Decl *Group[2] = { OwnedType, Ptr }; + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); + } + return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } diff --git a/test/SemaTemplate/instantiate-function-2.cpp b/test/SemaTemplate/instantiate-function-2.cpp index b4c0d9d639..21eccd4901 100644 --- a/test/SemaTemplate/instantiate-function-2.cpp +++ b/test/SemaTemplate/instantiate-function-2.cpp @@ -42,3 +42,17 @@ namespace PR9654 { f(0); } } + +namespace AliasTagDef { + template + T f() { + using S = struct { // expected-warning {{C++0x}} + T g() { + return T(); + } + }; + return S().g(); + } + + int n = f(); +} diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp index 74c2609dcd..1028b45cc0 100644 --- a/test/SemaTemplate/instantiate-member-class.cpp +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -104,3 +104,17 @@ namespace test2 { }; template class C; } + +namespace AliasTagDef { + template + struct F { + using S = struct U { // expected-warning {{C++0x}} + T g() { + return T(); + } + }; + }; + + int m = F::S().g(); + int n = F::U().g(); +}