]> granicus.if.org Git - clang/commitdiff
Properly handle typos in the conditional of ?: expressions in C.
authorKaelyn Takata <rikka@google.com>
Tue, 27 Jan 2015 18:26:18 +0000 (18:26 +0000)
committerKaelyn Takata <rikka@google.com>
Tue, 27 Jan 2015 18:26:18 +0000 (18:26 +0000)
In particular, remove the OpaqueExpr transformation from r225389 and
move the correction of the conditional from CheckConditionalOperands to
ActOnConditionalOp before the OpaqueExpr is created. This fixes the
typo correction behavior in C code that uses the GNU extension for a
binary ?: (without an expression between the "?" and the ":").

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227220 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
test/Sema/typo-correction.c

index 8b9950847f5b2aeaa17d05c611164a94d5584fb5..2b507141e97544404b7431e8b9c67ee1e110d5eb 100644 (file)
@@ -5785,15 +5785,6 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
                                         ExprObjectKind &OK,
                                         SourceLocation QuestionLoc) {
 
-  if (!getLangOpts().CPlusPlus) {
-    // C cannot handle TypoExpr nodes on either side of a binop because it
-    // doesn't handle dependent types properly, so make sure any TypoExprs have
-    // been dealt with before checking the operands.
-    ExprResult CondResult = CorrectDelayedTyposInExpr(Cond);
-    if (!CondResult.isUsable()) return QualType();
-    Cond = CondResult;
-  }
-
   ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
   if (!LHSResult.isUsable()) return QualType();
   LHS = LHSResult;
@@ -6175,6 +6166,15 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
                                     SourceLocation ColonLoc,
                                     Expr *CondExpr, Expr *LHSExpr,
                                     Expr *RHSExpr) {
+  if (!getLangOpts().CPlusPlus) {
+    // C cannot handle TypoExpr nodes in the condition because it
+    // doesn't handle dependent types properly, so make sure any TypoExprs have
+    // been dealt with before checking the operands.
+    ExprResult CondResult = CorrectDelayedTyposInExpr(CondExpr);
+    if (!CondResult.isUsable()) return ExprError();
+    CondExpr = CondResult.get();
+  }
+
   // If this is the gnu "x ?: y" extension, analyze the types as though the LHS
   // was the condition.
   OpaqueValueExpr *opaqueValue = nullptr;
index 4de25c63b766e04fe74c8185709e5d4a4f919a5f..bf4ab267a411c5bff5f68f62f9d025ff5d91e470 100644 (file)
@@ -6146,12 +6146,6 @@ public:
 
   ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
 
-  ExprResult TransformOpaqueValueExpr(OpaqueValueExpr *E) {
-    if (Expr *SE = E->getSourceExpr())
-      return TransformExpr(SE);
-    return BaseTransform::TransformOpaqueValueExpr(E);
-  }
-
   ExprResult Transform(Expr *E) {
     ExprResult Res;
     while (true) {
index df7da797f050b1f9edee18499aa051f4c869372c..8276737e4fec654de1d7e3dfa6ca18e2c9baa091 100644 (file)
@@ -13,6 +13,11 @@ void PR21656() {
 a = b ? : 0;  // expected-warning {{type specifier missing, defaults to 'int'}} \
               // expected-error {{use of undeclared identifier 'b'}}
 
+int foobar;  // expected-note {{'foobar' declared here}}
+a = goobar ?: 4;  // expected-warning {{type specifier missing, defaults to 'int'}} \
+                  // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \
+                  // expected-error {{initializer element is not a compile-time constant}}
+
 struct ContainerStuct {
   enum { SOME_ENUM }; // expected-note {{'SOME_ENUM' declared here}}
 };