diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-06-21 05:54:55 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-06-21 05:54:55 +0000 |
commit | 81a5641e5f446d0e879595d3659e76845c7a9410 (patch) | |
tree | 0d399123fc447800a52e33106f9e0b001b1463a4 /lib/Sema/SemaStmt.cpp | |
parent | 05233276b5b0d76e9ebd75eaa2709dff9b316590 (diff) |
Pretend that enum constants have enum type when inferring a block return type.
In C, enum constants have the type of the enum's underlying integer type,
rather than the type of the enum. (This is not true in C++.) This leads to
odd warnings when returning enum constants directly in blocks with inferred
return types. The easiest way out of this is to pretend that, like C++, enum
constants have enum type when being returned from a block.
<rdar://problem/11662489>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158899 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 8bf0b7326d..999be9109d 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2128,10 +2128,32 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return StmtError(); RetValExp = Result.take(); - if (!RetValExp->isTypeDependent()) + if (!RetValExp->isTypeDependent()) { ReturnT = RetValExp->getType(); - else + + // In C, enum constants have the type of their underlying integer type, + // not the enum. When inferring block return values, we should infer + // the enum type if an enum constant is used, unless the enum is + // anonymous (in which case there can be no variables of its type). + if (!getLangOpts().CPlusPlus) { + Expr *InsideExpr = RetValExp->IgnoreParenImpCasts(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InsideExpr)) { + Decl *D = DRE->getDecl(); + if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { + EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); + if (Enum->getDeclName() || Enum->getTypedefNameForAnonDecl()) { + ReturnT = Context.getTypeDeclType(Enum); + ExprResult Casted = ImpCastExprToType(RetValExp, ReturnT, + CK_IntegralCast); + assert(Casted.isUsable()); + RetValExp = Casted.take(); + } + } + } + } + } else { ReturnT = Context.DependentTy; + } } else { if (RetValExp) { // C++11 [expr.lambda.prim]p4 bans inferring the result from an @@ -2147,7 +2169,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (!CurCap->ReturnType.isNull() && !CurCap->ReturnType->isDependentType() && !ReturnT->isDependentType() && - !Context.hasSameType(ReturnT, CurCap->ReturnType)) { + !Context.hasSameType(ReturnT, CurCap->ReturnType)) { Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) << ReturnT << CurCap->ReturnType << (getCurLambda() != 0); |