/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a /// C++ if/switch/while/for statement. /// e.g: "if (int x = f()) {...}" Action::OwningExprResult Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc, Declarator &D, SourceLocation EqualLoc, ExprArg AssignExprVal) { assert(AssignExprVal.get() && "Null assignment expression"); // C++ 6.4p2: // The declarator shall not specify a function or an array. // The type-specifier-seq shall not contain typedef and shall not declare a // new class or enumeration. assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class of condition decl."); QualType Ty = GetTypeForDeclarator(D, S); 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. return ExprError(Diag(StartLoc, diag::err_invalid_use_of_function_type) << SourceRange(StartLoc, EqualLoc)); } else if (Ty->isArrayType()) { // ...or an array. Diag(StartLoc, diag::err_invalid_use_of_array_type) << SourceRange(StartLoc, EqualLoc); } else if (const RecordType *RT = Ty->getAsRecordType()) { RecordDecl *RD = RT->getDecl(); // The type-specifier-seq shall not declare a new class... if (RD->isDefinition() && (RD->getIdentifier() == 0 || S->isDeclScope(DeclPtrTy::make(RD)))) Diag(RD->getLocation(), diag::err_type_defined_in_condition); } else if (const EnumType *ET = Ty->getAsEnumType()) { EnumDecl *ED = ET->getDecl(); // ...or enumeration. if (ED->isDefinition() && (ED->getIdentifier() == 0 || S->isDeclScope(DeclPtrTy::make(ED)))) Diag(ED->getLocation(), diag::err_type_defined_in_condition); } DeclPtrTy Dcl = ActOnDeclarator(S, D, DeclPtrTy()); if (!Dcl) return ExprError(); AddInitializerToDecl(Dcl, move(AssignExprVal)); // Mark this variable as one that is declared within a conditional. // We know that the decl had to be a VarDecl because that is the only type of // decl that can be assigned and the grammar requires an '='. VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>()); VD->setDeclaredInCondition(true); return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD)); }