diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 36 | ||||
-rw-r--r-- | test/SemaCXX/condition.cpp | 1 |
3 files changed, 40 insertions, 17 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 07eb9fe572..c0d34da922 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -8913,25 +8913,13 @@ DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { // new class or enumeration. assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class of condition decl."); - - TagDecl *OwnedTag = 0; - TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag); - QualType Ty = TInfo->getType(); - - if (Ty->isFunctionType()) { // The declarator shall not specify a function... - // We exit without creating a CXXConditionDeclExpr because a FunctionDecl - // would be created and CXXConditionDeclExpr wants a VarDecl. - Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type) + + Decl *Dcl = ActOnDeclarator(S, D); + if (isa<FunctionDecl>(Dcl)) { // The declarator shall not specify a function. + Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type) << D.getSourceRange(); return DeclResult(); - } else if (OwnedTag && OwnedTag->isDefinition()) { - // The type-specifier-seq shall not declare a new class or enumeration. - Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); } - - Decl *Dcl = ActOnDeclarator(S, D); - if (!Dcl) - return DeclResult(); return Dcl; } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index ea1086c867..489e50dc1c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1728,6 +1728,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // have a type. QualType T; TypeSourceInfo *ReturnTypeInfo = 0; + TagDecl *OwnedTagDeclInternal = 0; TypeProcessingState state(*this, D); @@ -1752,7 +1753,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); // Owned declaration is embedded in declarator. Owned->setEmbeddedInDeclarator(true); - if (OwnedDecl) *OwnedDecl = Owned; + OwnedTagDeclInternal = Owned; } break; @@ -2456,6 +2457,39 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, return Context.getNullTypeSourceInfo(); else if (D.isInvalidType()) return Context.getTrivialTypeSourceInfo(T); + + if (OwnedTagDeclInternal && OwnedDecl) + *OwnedDecl = OwnedTagDeclInternal; + + if (getLangOptions().CPlusPlus && + OwnedTagDeclInternal && OwnedTagDeclInternal->isDefinition()) { + // Check the contexts where C++ forbids the declaration of a new class + // or enumeration in a type-specifier-seq. + switch (D.getContext()) { + case Declarator::FileContext: + case Declarator::PrototypeContext: + case Declarator::ObjCPrototypeContext: + case Declarator::KNRTypeListContext: + case Declarator::TypeNameContext: + case Declarator::MemberContext: + case Declarator::BlockContext: + case Declarator::ForContext: + case Declarator::TemplateParamContext: + case Declarator::CXXCatchContext: + case Declarator::BlockLiteralContext: + case Declarator::TemplateTypeArgContext: + case Declarator::AliasDeclContext: + case Declarator::AliasTemplateContext: + break; + case Declarator::ConditionContext: + // C++ 6.4p2: + // The type-specifier-seq shall not contain typedef and shall not declare + // a new class or enumeration. + Diag(OwnedTagDeclInternal->getLocation(), diag::err_type_defined_in_condition); + break; + } + } + return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); } diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index cb7391a5f1..3441bae670 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -16,6 +16,7 @@ void test() { for (;s;) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} + while (struct NewS *x=0) ; while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}} while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}} switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ |