Hi Reid, Following this change, we started seeing an assertion failure in one of our C tests. I have filed bug 31366 for the issue. Can you take a look?
Douglas Yung > -----Original Message----- > From: cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] On Behalf > Of Reid Kleckner via cfe-commits > Sent: Friday, December 09, 2016 9:14 > To: cfe-commits@lists.llvm.org > Subject: r289225 - Store decls in prototypes on the declarator instead > of in the AST > > Author: rnk > Date: Fri Dec 9 11:14:05 2016 > New Revision: 289225 > > URL: http://llvm.org/viewvc/llvm-project?rev=289225&view=rev > Log: > Store decls in prototypes on the declarator instead of in the AST > > This saves two pointers from FunctionDecl that were being used for some > rare and questionable C-only functionality. The DeclsInPrototypeScope > ArrayRef was added in r151712 in order to parse this kind of C code: > > enum e {x, y}; > int f(enum {y, x} n) { > return x; // should return 1, not 0 > } > > The challenge is that we parse 'int f(enum {y, x} n)' it its own > function prototype scope that gets popped before we build the > FunctionDecl for 'f'. The original change was doing two questionable > things: > > 1. Saving all tag decls introduced in prototype scope on a TU-global > Sema variable. This is problematic when you have cases like this, where > 'x' and 'y' shouldn't be visible in 'f': > void f(void (*fp)(enum { x, y } e)) { /* no x */ } This patch fixes > that, so now 'f' can't see 'x', which is consistent with GCC. > > 2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that > they could be used in ActOnStartOfFunctionDef. This is just an > inefficient way to move information around. The AST lives forever, but > the list of non-parameter decls in prototype scope is short lived. > > Moving these things to the Declarator solves both of these issues. > > Reviewers: rsmith > > Subscribers: jmolloy, cfe-commits > > Differential Revision: https://reviews.llvm.org/D27279 > > Added: > cfe/trunk/test/PCH/decl-in-prototype.c > Modified: > cfe/trunk/include/clang/AST/Decl.h > cfe/trunk/include/clang/Sema/DeclSpec.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/AST/ASTDumper.cpp > cfe/trunk/lib/AST/Decl.cpp > cfe/trunk/lib/Parse/ParseDecl.cpp > cfe/trunk/lib/Parse/ParseExpr.cpp > cfe/trunk/lib/Parse/ParseExprCXX.cpp > cfe/trunk/lib/Sema/DeclSpec.cpp > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp > cfe/trunk/lib/Sema/SemaType.cpp > cfe/trunk/test/Misc/ast-dump-decl.c > cfe/trunk/test/Sema/decl-in-prototype.c > cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp > > Modified: cfe/trunk/include/clang/AST/Decl.h > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/include/clang/AST/Decl.h?rev=289225&r1=289224&r2=2892 > 25&view=diff > ======================================================================= > ======= > --- cfe/trunk/include/clang/AST/Decl.h (original) > +++ cfe/trunk/include/clang/AST/Decl.h Fri Dec 9 11:14:05 2016 > @@ -1601,11 +1601,6 @@ private: > /// no formals. > ParmVarDecl **ParamInfo; > > - /// DeclsInPrototypeScope - Array of pointers to NamedDecls for > - /// decls defined in the function prototype that are not parameters. > E.g. > - /// 'enum Y' in 'void f(enum Y {AA} x) {}'. > - ArrayRef<NamedDecl *> DeclsInPrototypeScope; > - > LazyDeclStmtPtr Body; > > // FIXME: This can be packed into the bitfields in DeclContext. > @@ -2050,11 +2045,6 @@ public: > setParams(getASTContext(), NewParamInfo); > } > > - ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const { > - return DeclsInPrototypeScope; > - } > - void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls); > - > /// getMinRequiredArguments - Returns the minimum number of > arguments > /// needed to call this function. This may be fewer than the number > of > /// function parameters, if some of the parameters have default > > Modified: cfe/trunk/include/clang/Sema/DeclSpec.h > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=289225&r1=289224&r2 > =289225&view=diff > ======================================================================= > ======= > --- cfe/trunk/include/clang/Sema/DeclSpec.h (original) > +++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Dec 9 11:14:05 2016 > @@ -1248,9 +1248,10 @@ struct DeclaratorChunk { > /// declarator. > unsigned NumParams; > > - /// NumExceptions - This is the number of types in the dynamic- > exception- > - /// decl, if the function has one. > - unsigned NumExceptions; > + /// NumExceptionsOrDecls - This is the number of types in the > + /// dynamic-exception-decl, if the function has one. In C, this is > the > + /// number of declarations in the function prototype. > + unsigned NumExceptionsOrDecls; > > /// \brief The location of the ref-qualifier, if any. > /// > @@ -1300,6 +1301,11 @@ struct DeclaratorChunk { > /// \brief Pointer to the cached tokens for an exception- > specification > /// that has not yet been parsed. > CachedTokens *ExceptionSpecTokens; > + > + /// Pointer to a new[]'d array of declarations that need to be > available > + /// for lookup inside the function body, if one exists. Does not > exist in > + /// C++. > + NamedDecl **DeclsInPrototype; > }; > > /// \brief If HasTrailingReturnType is true, this is the trailing > return @@ -1322,10 +1328,20 @@ struct DeclaratorChunk { > void destroy() { > if (DeleteParams) > delete[] Params; > - if (getExceptionSpecType() == EST_Dynamic) > + switch (getExceptionSpecType()) { > + default: > + break; > + case EST_Dynamic: > delete[] Exceptions; > - else if (getExceptionSpecType() == EST_Unparsed) > + break; > + case EST_Unparsed: > delete ExceptionSpecTokens; > + break; > + case EST_None: > + if (NumExceptionsOrDecls != 0) > + delete[] DeclsInPrototype; > + break; > + } > } > > /// isKNRPrototype - Return true if this is a K&R style identifier > list, @@ -1395,6 +1411,19 @@ struct DeclaratorChunk { > return > static_cast<ExceptionSpecificationType>(ExceptionSpecType); > } > > + /// \brief Get the number of dynamic exception specifications. > + unsigned getNumExceptions() const { > + assert(ExceptionSpecType != EST_None); > + return NumExceptionsOrDecls; > + } > + > + /// \brief Get the non-parameter decls defined within this > function > + /// prototype. Typically these are tag declarations. > + ArrayRef<NamedDecl *> getDeclsInPrototype() const { > + assert(ExceptionSpecType == EST_None); > + return llvm::makeArrayRef(DeclsInPrototype, > NumExceptionsOrDecls); > + } > + > /// \brief Determine whether this function declarator had a > /// trailing-return-type. > bool hasTrailingReturnType() const { return HasTrailingReturnType; > } @@ -1540,6 +1569,7 @@ struct DeclaratorChunk { > unsigned NumExceptions, > Expr *NoexceptExpr, > CachedTokens > *ExceptionSpecTokens, > + ArrayRef<NamedDecl *> > + DeclsInPrototype, > SourceLocation LocalRangeBegin, > SourceLocation LocalRangeEnd, > Declarator &TheDeclarator, > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/include/clang/Sema/Sema.h?rev=289225&r1=289224&r2=289 > 225&view=diff > ======================================================================= > ======= > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Fri Dec 9 11:14:05 2016 > @@ -1527,12 +1527,6 @@ public: > NamedDecl *Previous; > }; > > - /// List of decls defined in a function prototype. This contains > EnumConstants > - /// that incorrectly end up in translation unit scope because there > is no > - /// function to pin them on. ActOnFunctionDeclarator reads this list > and patches > - /// them into the FunctionDecl. > - std::vector<NamedDecl*> DeclsInPrototypeScope; > - > DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = > nullptr); > > void DiagnoseUseOfUnimplementedSelectors(); > > Modified: cfe/trunk/lib/AST/ASTDumper.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=289225&r1=289224&r2=289225& > view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/AST/ASTDumper.cpp (original) > +++ cfe/trunk/lib/AST/ASTDumper.cpp Fri Dec 9 11:14:05 2016 > @@ -1164,11 +1164,6 @@ void ASTDumper::VisitFunctionDecl(const > D->getTemplateSpecializationInfo()) > dumpTemplateArgumentList(*FTSI->TemplateArguments); > > - for (ArrayRef<NamedDecl *>::iterator > - I = D->getDeclsInPrototypeScope().begin(), > - E = D->getDeclsInPrototypeScope().end(); I != E; ++I) > - dumpDecl(*I); > - > if (!D->param_begin() && D->getNumParams()) > dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << > ">>"; }); > else > > Modified: cfe/trunk/lib/AST/Decl.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/AST/Decl.cpp?rev=289225&r1=289224&r2=289225&view= > diff > ======================================================================= > ======= > --- cfe/trunk/lib/AST/Decl.cpp (original) > +++ cfe/trunk/lib/AST/Decl.cpp Fri Dec 9 11:14:05 2016 > @@ -2840,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext > } > } > > -void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> > NewDecls) { > - assert(DeclsInPrototypeScope.empty() && "Already has prototype > decls!"); > - > - if (!NewDecls.empty()) { > - NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; > - std::copy(NewDecls.begin(), NewDecls.end(), A); > - DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size()); > - // Move declarations introduced in prototype to the function > context. > - for (auto I : NewDecls) { > - DeclContext *DC = I->getDeclContext(); > - // Forward-declared reference to an enumeration is not added to > - // declaration scope, so skip declaration that is absent from > its > - // declaration contexts. > - if (DC->containsDecl(I)) { > - DC->removeDecl(I); > - I->setDeclContext(this); > - addDecl(I); > - } > - } > - } > -} > - > /// getMinRequiredArguments - Returns the minimum number of arguments > /// needed to call this function. This may be fewer than the number of > /// function parameters, if some of the parameters have default > > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=289225&r1=289224&r2=28922 > 5&view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Dec 9 11:14:05 2016 > @@ -5827,6 +5827,21 @@ void Parser::ParseFunctionDeclarator(Dec > } > } > > + // Collect non-parameter declarations from the prototype if this is > a > + function // declaration. They will be moved into the scope of the > + function. Only do // this in C and not C++, where the decls will > + continue to live in the // surrounding context. > + SmallVector<NamedDecl *, 0> DeclsInPrototype; if > + (getCurScope()->getFlags() & Scope::FunctionDeclarationScope && > + !getLangOpts().CPlusPlus) { > + for (Decl *D : getCurScope()->decls()) { > + NamedDecl *ND = dyn_cast<NamedDecl>(D); > + if (!ND || isa<ParmVarDecl>(ND)) > + continue; > + DeclsInPrototype.push_back(ND); > + } > + } > + > // Remember that we parsed a function type, and remember the > attributes. > D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, > IsAmbiguous, @@ -5846,6 > +5861,7 @@ void Parser::ParseFunctionDeclarator(Dec > NoexceptExpr.isUsable() ? > NoexceptExpr.get() : > nullptr, > ExceptionSpecTokens, > + DeclsInPrototype, > StartLoc, LocalEndLoc, D, > TrailingReturnType), > FnAttrs, EndLoc); > > Modified: cfe/trunk/lib/Parse/ParseExpr.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=289225&r1=289224&r2=28922 > 5&view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) > +++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Dec 9 11:14:05 2016 > @@ -2842,6 +2842,7 @@ ExprResult Parser::ParseBlockLiteralExpr > /*NumExceptions=*/0, > /*NoexceptExpr=*/nullptr, > > /*ExceptionSpecTokens=*/nullptr, > + > /*DeclsInPrototype=*/None, > CaretLoc, CaretLoc, > ParamInfo), > attrs, CaretLoc); > > Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=289225&r1=289224&r2=28 > 9225&view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) > +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Dec 9 11:14:05 2016 > @@ -1244,6 +1244,7 @@ ExprResult Parser::ParseLambdaExpression > NoexceptExpr.isUsable() ? > NoexceptExpr.get() : > nullptr, > > /*ExceptionSpecTokens*/nullptr, > + /*DeclsInPrototype=*/None, > LParenLoc, > FunLocalRangeEnd, D, > TrailingReturnType), > Attr, DeclEndLoc); > @@ -1313,6 +1314,7 @@ ExprResult Parser::ParseLambdaExpression > /*NumExceptions=*/0, > > /*NoexceptExpr=*/nullptr, > > /*ExceptionSpecTokens=*/nullptr, > + > + /*DeclsInPrototype=*/None, > DeclLoc, DeclEndLoc, D, > TrailingReturnType), > Attr, DeclEndLoc); > > Modified: cfe/trunk/lib/Sema/DeclSpec.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=289225&r1=289224&r2=289225& > view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Sema/DeclSpec.cpp (original) > +++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Dec 9 11:14:05 2016 > @@ -173,6 +173,8 @@ DeclaratorChunk DeclaratorChunk::getFunc > unsigned NumExceptions, > Expr *NoexceptExpr, > CachedTokens > *ExceptionSpecTokens, > + ArrayRef<NamedDecl*> > + DeclsInPrototype, > SourceLocation > LocalRangeBegin, > SourceLocation > LocalRangeEnd, > Declarator > &TheDeclarator, @@ -204,7 +206,7 @@ DeclaratorChunk > DeclaratorChunk::getFunc > I.Fun.ExceptionSpecType = ESpecType; > I.Fun.ExceptionSpecLocBeg = > ESpecRange.getBegin().getRawEncoding(); > I.Fun.ExceptionSpecLocEnd = > ESpecRange.getEnd().getRawEncoding(); > - I.Fun.NumExceptions = 0; > + I.Fun.NumExceptionsOrDecls = 0; > I.Fun.Exceptions = nullptr; > I.Fun.NoexceptExpr = nullptr; > I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || > @@ -240,7 +242,7 @@ DeclaratorChunk DeclaratorChunk::getFunc > case EST_Dynamic: > // new[] an exception array if needed > if (NumExceptions) { > - I.Fun.NumExceptions = NumExceptions; > + I.Fun.NumExceptionsOrDecls = NumExceptions; > I.Fun.Exceptions = new > DeclaratorChunk::TypeAndRange[NumExceptions]; > for (unsigned i = 0; i != NumExceptions; ++i) { > I.Fun.Exceptions[i].Ty = Exceptions[i]; @@ -257,6 +259,17 @@ > DeclaratorChunk DeclaratorChunk::getFunc > I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; > break; > } > + > + if (!DeclsInPrototype.empty()) { > + assert(ESpecType == EST_None && NumExceptions == 0 && > + "cannot have exception specifiers and decls in prototype"); > + I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size(); > + // Copy the array of decls into stable heap storage. > + I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()]; > + for (size_t J = 0; J < DeclsInPrototype.size(); ++J) > + I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J]; } > + > return I; > } > > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=289225&r1=289224&r2=289225& > view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 9 11:14:05 2016 > @@ -8222,8 +8222,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, > // Copy the parameter declarations from the declarator D to the > function > // declaration NewFD, if they are available. First scavenge them > into Params. > SmallVector<ParmVarDecl*, 16> Params; > - if (D.isFunctionDeclarator()) { > - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); > + unsigned FTIIdx; > + if (D.isFunctionDeclarator(FTIIdx)) { > + DeclaratorChunk::FunctionTypeInfo &FTI = > + D.getTypeObject(FTIIdx).Fun; > > // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs > // function that takes no arguments, not a function that takes a > @@ -8241,6 +8242,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, > NewFD->setInvalidDecl(); > } > } > + > + if (!getLangOpts().CPlusPlus) { > + // In C, find all the non-parameter declarations from the > prototype and > + // move them into the new function decl context as well. > Typically they > + // will have been added to the surrounding context of the > prototype. > + for (NamedDecl *NonParmDecl : FTI.getDeclsInPrototype()) { > + DeclContext *OldDC = NonParmDecl->getDeclContext(); > + if (OldDC->containsDecl(NonParmDecl)) > + OldDC->removeDecl(NonParmDecl); > + NonParmDecl->setDeclContext(NewFD); > + NewFD->addDecl(NonParmDecl); > + } > + } > } else if (const FunctionProtoType *FT = R- > >getAs<FunctionProtoType>()) { > // When we're declaring a function with a typedef, typeof, etc as > in the > // following example, we'll need to synthesize (unnamed) @@ - > 8266,15 +8280,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, > // Finally, we know we have the right number of parameters, install > them. > NewFD->setParams(Params); > > - // Find all anonymous symbols defined during the declaration of this > function > - // and add to NewFD. This lets us track decls such 'enum Y' in: > - // > - // void f(enum Y {AA} x) {} > - // > - // which would otherwise incorrectly end up in the translation unit > scope. > - NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope); > - DeclsInPrototypeScope.clear(); > - > if (D.getDeclSpec().isNoreturnSpecified()) > NewFD->addAttr( > ::new(Context) > C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(), > @@ -11632,6 +11637,29 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop > CheckParmsForFunctionDef(FD->parameters(), > /*CheckParameterNames=*/true); > > + // Add non-parameter declarations already in the function to the > + current // scope. > + if (FnBodyScope) { > + for (Decl *NPD : FD->decls()) { > + auto *NonParmDecl = dyn_cast<NamedDecl>(NPD); > + if (!NonParmDecl) > + continue; > + assert(!isa<ParmVarDecl>(NonParmDecl) && > + "parameters should not be in newly created FD yet"); > + > + // If the decl has a name, make it accessible in the current > scope. > + if (NonParmDecl->getDeclName()) > + PushOnScopeChains(NonParmDecl, FnBodyScope, > + /*AddToContext=*/false); > + > + // Similarly, dive into enums and fish their constants out, > making them > + // accessible in this scope. > + if (auto *ED = dyn_cast<EnumDecl>(NonParmDecl)) { > + for (auto *EI : ED->enumerators()) > + PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false); > + } > + } > + } > + > // Introduce our parameters into the function scope > for (auto Param : FD->parameters()) { > Param->setOwningFunction(FD); > @@ -11644,39 +11672,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop > } > } > > - // If we had any tags defined in the function prototype, > - // introduce them into the function scope. > - if (FnBodyScope) { > - for (ArrayRef<NamedDecl *>::iterator > - I = FD->getDeclsInPrototypeScope().begin(), > - E = FD->getDeclsInPrototypeScope().end(); > - I != E; ++I) { > - NamedDecl *D = *I; > - > - // Some of these decls (like enums) may have been pinned to the > - // translation unit for lack of a real context earlier. If so, > remove > - // from the translation unit and reattach to the current > context. > - if (D->getLexicalDeclContext() == > Context.getTranslationUnitDecl()) { > - // Is the decl actually in the context? > - if (Context.getTranslationUnitDecl()->containsDecl(D)) > - Context.getTranslationUnitDecl()->removeDecl(D); > - // Either way, reassign the lexical decl context to our > FunctionDecl. > - D->setLexicalDeclContext(CurContext); > - } > - > - // If the decl has a non-null name, make accessible in the > current scope. > - if (!D->getName().empty()) > - PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false); > - > - // Similarly, dive into enums and fish their constants out, > making them > - // accessible in this scope. > - if (auto *ED = dyn_cast<EnumDecl>(D)) { > - for (auto *EI : ED->enumerators()) > - PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false); > - } > - } > - } > - > // Ensure that the function's exception specification is > instantiated. > if (const FunctionProtoType *FPT = FD->getType()- > >getAs<FunctionProtoType>()) > ResolveExceptionSpec(D->getLocation(), FPT); @@ -12161,6 +12156,7 > @@ NamedDecl *Sema::ImplicitlyDefineFunctio > /*NumExceptions=*/0, > /*NoexceptExpr=*/nullptr, > > /*ExceptionSpecTokens=*/nullptr, > + > /*DeclsInPrototype=*/None, > Loc, Loc, D), > DS.getAttributes(), > SourceLocation()); > @@ -13430,7 +13426,6 @@ CreateNewDecl: > } else if (!PrevDecl) { > Diag(Loc, diag::warn_decl_in_param_list) << > Context.getTagDeclType(New); > } > - DeclsInPrototypeScope.push_back(New); > } > > if (Invalid) > > Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=289225&r1=28922 > 4&r2=289225&view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Fri Dec 9 11:14:05 > 2016 > @@ -772,7 +772,7 @@ bool Sema::containsUnexpandedParameterPa > } > > if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { > - for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) { > + for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) { > if (Chunk.Fun.Exceptions[i] > .Ty.get() > ->containsUnexpandedParameterPack()) > > Modified: cfe/trunk/lib/Sema/SemaType.cpp > URL: http://llvm.org/viewvc/llvm- > project/cfe/trunk/lib/Sema/SemaType.cpp?rev=289225&r1=289224&r2=289225& > view=diff > ======================================================================= > ======= > --- cfe/trunk/lib/Sema/SemaType.cpp (original) > +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Dec 9 11:14:05 2016 > @@ -718,6 +718,7 @@ static void maybeSynthesizeBlockSignatur > /*NumExceptions=*/0, > /*NoexceptExpr=*/nullptr, > /*ExceptionSpecTokens=*/nullptr, > + /*DeclsInPrototype=*/None, > loc, loc, declarator)); > > // For consistency, make sure the state still has us as processing > @@ -4469,7 +4470,7 @@ static TypeSourceInfo *GetFullTypeForDec > if (FTI.getExceptionSpecType() == EST_Dynamic) { > // FIXME: It's rather inefficient to have to split into two > vectors > // here. > - unsigned N = FTI.NumExceptions; > + unsigned N = FTI.getNumExceptions(); > DynamicExceptions.reserve(N); > DynamicExceptionRanges.reserve(N); > for (unsigned I = 0; I != N; ++I) { > > Modified: cfe/trunk/test/Misc/ast-dump-decl.c > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump- > decl.c?rev=289225&r1=289224&r2=289225&view=diff > ======================================================================= > ======= > --- cfe/trunk/test/Misc/ast-dump-decl.c (original) > +++ cfe/trunk/test/Misc/ast-dump-decl.c Fri Dec 9 11:14:05 2016 > @@ -102,16 +102,22 @@ struct testIndirectFieldDecl { > // CHECK-NEXT: Field{{.*}} '' > // CHECK-NEXT: Field{{.*}} 'TestIndirectFieldDecl' > > +// FIXME: It would be nice to dump the enum and its enumerators. > int TestFunctionDecl(int x, enum { e } y) { > return x; > } > // CHECK: FunctionDecl{{.*}} TestFunctionDecl 'int (int, enum > {{.*}})' > -// CHECK-NEXT: EnumDecl > -// CHECK-NEXT: EnumConstantDecl{{.*}} e > // CHECK-NEXT: ParmVarDecl{{.*}} x > // CHECK-NEXT: ParmVarDecl{{.*}} y > // CHECK-NEXT: CompoundStmt > > +// FIXME: It would be nice to 'Enum' and 'e'. > +int TestFunctionDecl2(enum Enum { e } x) { return x; } > +// CHECK: FunctionDecl{{.*}} TestFunctionDecl2 'int (enum > {{.*}})' > +// CHECK-NEXT: ParmVarDecl{{.*}} x > +// CHECK-NEXT: CompoundStmt > + > + > int TestFunctionDeclProto(int x); > // CHECK: FunctionDecl{{.*}} TestFunctionDeclProto 'int (int)' > // CHECK-NEXT: ParmVarDecl{{.*}} x > > Added: cfe/trunk/test/PCH/decl-in-prototype.c > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/decl-in- > prototype.c?rev=289225&view=auto > ======================================================================= > ======= > --- cfe/trunk/test/PCH/decl-in-prototype.c (added) > +++ cfe/trunk/test/PCH/decl-in-prototype.c Fri Dec 9 11:14:05 2016 > @@ -0,0 +1,27 @@ > +// Test that we serialize the enum decl in the function prototype > somehow. > +// These decls aren't serialized quite the same way as parameters. > + > +// Test this without pch. > +// RUN: %clang_cc1 -include %s -emit-llvm -o - %s | FileCheck %s > + > +// Test with pch. > +// RUN: %clang_cc1 -emit-pch -o %t %s > +// RUN: %clang_cc1 -include-pch %t -emit-llvm -o - %s | FileCheck %s > + > +// CHECK-LABEL: define i32 @main() > +// CHECK: ret i32 1 > + > +#ifndef HEADER > +#define HEADER > + > +static inline __attribute__((always_inline)) f(enum { x, y } p) { > + return y; > +} > + > +#else > + > +int main() { > + return f(0); > +} > + > +#endif > > Modified: cfe/trunk/test/Sema/decl-in-prototype.c > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/decl-in- > prototype.c?rev=289225&r1=289224&r2=289225&view=diff > ======================================================================= > ======= > --- cfe/trunk/test/Sema/decl-in-prototype.c (original) > +++ cfe/trunk/test/Sema/decl-in-prototype.c Fri Dec 9 11:14:05 2016 > @@ -1,13 +1,19 @@ > // RUN: %clang_cc1 -fsyntax-only -verify %s > > +#define SA(n, c) int arr##n[(c) ? 1 : -1] = {} > + > const int AA = 5; > > int f1(enum {AA,BB} E) { // expected-warning {{will not be visible > outside of this function}} > - return BB; > + SA(1, AA == 0); > + SA(2, BB == 1); > + return BB; > } > > int f2(enum {AA=7,BB} E) { // expected-warning {{will not be visible > outside of this function}} > - return AA; > + SA(1, AA == 7); > + SA(2, BB == 8); > + return AA; > } > > struct a { > @@ -38,3 +44,11 @@ enum e19018 qq; //expected-error{{tentat > > // Only warn once, even if we create two declarations. > void f(struct q *, struct __attribute__((aligned(4))) q *); // > expected-warning {{will not be visible outside}} > + > +// This enum inside the function pointer parameter shouldn't leak into > +the // function. > +enum { BB = 0 }; > +void enum_in_fun_in_fun(void (*fp)(enum { AA, BB } e)) { // > +expected-warning {{will not be visible}} > + SA(1, AA == 5); > + SA(2, BB == 0); > +} > > Modified: cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type- > definition-in-specifier.cpp?rev=289225&r1=289224&r2=289225&view=diff > ======================================================================= > ======= > --- cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp (original) > +++ cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp Fri Dec 9 > +++ 11:14:05 2016 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s > > struct S0; > struct S1; > @@ -30,7 +30,7 @@ struct pr19018 { > > void pr19018_1 (enum e19018_1 {qq} x); // expected-error{{cannot be > defined in a parameter type}} void pr19018_1a (enum e19018_1 {qq} x); > // expected-error{{cannot be defined in a parameter type}} > -e19018_1 x2; // expected-error{{unknown type name 'e19018_1'}} > +e19018_1 x2; > > void pr19018_2 (enum {qq} x); // expected-error{{cannot be defined in > a parameter type}} void pr19018_3 (struct s19018_2 {int qq;} x); // > expected-error{{cannot be defined in a parameter type}} @@ -53,14 > +53,19 @@ struct pr19018a { > > struct s19018b { > void func1 (enum en_2 {qq} x); // expected-error{{cannot be defined > in a parameter type}} > - en_2 x1; // expected-error{{unknown type name 'en_2'}} > + en_2 x1; > void func2 (enum en_3 {qq} x); // expected-error{{cannot be defined > in a parameter type}} > - enum en_3 x2; // expected-error{{ISO C++ forbids forward references > to 'enum' types}} \ > - // expected-error{{field has incomplete type 'enum > en_3'}} \ > - // expected-note{{forward declaration of 'en_3'}} > + enum en_3 x2; > }; > > struct pr18963 { > - short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot > be defined in a parameter type}} > - long foo5 (float foo6 = foo4); // expected-error{{use of undeclared > identifier 'foo4'}} > + short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot > be defined in a parameter type}} \ > + // expected-note{{declared here}} > + > + long foo5 (float foo6 = foo4); // expected-error{{'foo4' does not > + refer to a value}} > }; > + > +// expected-error@+2 {{cannot be defined in a parameter type}} // > +expected-note@+1 {{previous definition is here}} void > +func_with_eh_and_type(struct type_in_eh {} o) throw(int) {} struct > +type_in_eh {}; // expected-error {{redefinition of 'type_in_eh'}} > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits