aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-06-21 05:54:55 +0000
committerJordan Rose <jordan_rose@apple.com>2012-06-21 05:54:55 +0000
commit81a5641e5f446d0e879595d3659e76845c7a9410 (patch)
tree0d399123fc447800a52e33106f9e0b001b1463a4 /lib/Sema/SemaStmt.cpp
parent05233276b5b0d76e9ebd75eaa2709dff9b316590 (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.cpp28
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);