Index: cfe/trunk/lib/AST/Decl.cpp =================================================================== --- cfe/trunk/lib/AST/Decl.cpp +++ cfe/trunk/lib/AST/Decl.cpp @@ -2544,6 +2544,18 @@ NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); DeclsInPrototypeScope = ArrayRef(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); + } + } } } Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -10874,11 +10874,6 @@ while (isa(SearchDC) || isa(SearchDC)) SearchDC = SearchDC->getParent(); } - } else if (S->isFunctionPrototypeScope()) { - // If this is an enum declaration in function prototype scope, set its - // initial context to the translation unit. - // FIXME: [citation needed] - SearchDC = Context.getTranslationUnitDecl(); } if (Previous.isSingleResult() && @@ -11351,27 +11346,37 @@ else if (!SearchDC->isFunctionOrMethod()) New->setModulePrivate(); } - + // If this is a specialization of a member class (of a class template), // check the specialization. if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) Invalid = true; - - if (Invalid) - New->setInvalidDecl(); - - if (Attr) - ProcessDeclAttributeList(S, New, Attr); // If we're declaring or defining a tag in function prototype scope in C, // note that this type can only be used within the function and add it to // the list of decls to inject into the function definition scope. - if (!getLangOpts().CPlusPlus && (Name || Kind == TTK_Enum) && + if ((Name || Kind == TTK_Enum) && getNonFieldDeclScope(S)->isFunctionPrototypeScope()) { - Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); + if (getLangOpts().CPlusPlus) { + // C++ [dcl.fct]p6: + // Types shall not be defined in return or parameter types. + if (TUK == TUK_Definition && !IsTypeSpecifier) { + Diag(Loc, diag::err_type_defined_in_param_type) + << Name; + Invalid = true; + } + } else { + Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); + } DeclsInPrototypeScope.push_back(New); } + if (Invalid) + New->setInvalidDecl(); + + if (Attr) + ProcessDeclAttributeList(S, New, Attr); + // Set the lexical context. If the tag has a C++ scope specifier, the // lexical context will be different from the semantic context. New->setLexicalDeclContext(CurContext); Index: cfe/trunk/test/Sema/decl-in-prototype.c =================================================================== --- cfe/trunk/test/Sema/decl-in-prototype.c +++ cfe/trunk/test/Sema/decl-in-prototype.c @@ -31,3 +31,7 @@ struct z d; d.b = 4; } + +void pr19018_1 (enum e19018 { qq } x); // expected-warning{{declaration of 'enum e19018' will not be visible outside of this function}} +enum e19018 qq; //expected-error{{tentative definition has type 'enum e19018' that is never completed}} \ + //expected-note{{forward declaration of 'enum e19018'}} Index: cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp =================================================================== --- cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp +++ cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp @@ -23,3 +23,44 @@ struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}} void f2(struct S6 { int x; } p); // expected-error{{parameter type}} + +struct pr19018 { + short foo6 (enum bar0 {qq} bar3); // expected-error{{cannot be defined in a parameter type}} +}; + +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'}} + +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}} +void pr19018_4 (struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_5 (struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_5 (struct s19018_2 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + +struct pr19018a { + static int xx; + void func1(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func2(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func3(enum {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func4(struct t19018 {int qq;} x); // expected-error{{cannot be defined in a parameter type}} + void func5(struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}} + void func6(struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + void func7(struct t19018 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + void func8(struct { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}} + void func9(struct t19018 { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}} +}; + +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'}} + 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'}} +}; + +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'}} +};