Author: Haojian Wu
Date: 2020-04-07T14:29:38+02:00
New Revision: 041080c247351da15b6bb21a7196c8dc9bc6babc

URL: 
https://github.com/llvm/llvm-project/commit/041080c247351da15b6bb21a7196c8dc9bc6babc
DIFF: 
https://github.com/llvm/llvm-project/commit/041080c247351da15b6bb21a7196c8dc9bc6babc.diff

LOG: [AST] Fix a crash on invalid constexpr Ctorinitializer when building 
RecoveryExpr.

Summary:
crash stack:

```

lang:  workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:13704: bool 
EvaluateInPlace(clang::APValue &, (anonymous namespace)::EvalInfo &, const 
(anonymous namespace)::LValue &, const clang::Expr *, bool): Assertion 
`!E->isValueDependent()' failed.
 #8  EvaluateInPlace(clang::APValue&, (anonymous namespace)::EvalInfo&, 
(anonymous namespace)::LValue const&, clang::Expr const*, bool)  
workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:0:0
 #9  HandleConstructorCall(clang::Expr const*, (anonymous namespace)::LValue 
const&, clang::APValue*, clang::CXXConstructorDecl const*, (anonymous 
namespace)::EvalInfo&, clang::APValue&)  
workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:5779:57
#10  HandleConstructorCall(clang::Expr const*, (anonymous namespace)::LValue 
const&, llvm::ArrayRef<clang::Expr const*>, clang::CXXConstructorDecl const*, 
(anonymous namespace)::EvalInfo&, clang::APValue&)  
workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:5819:10
#11  clang::Expr::isPotentialConstantExpr(clang::FunctionDecl const*, 
llvm::SmallVectorImpl<std::pair<clang::SourceLocation, 
clang::PartialDiagnostic> >&) 
workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:14746:5
#12  CheckConstexprFunctionBody(clang::Sema&, clang::FunctionDecl const*, 
clang::Stmt*, clang::Sema::CheckConstexprKind)  
workspace/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:2306:7
#13  clang::Sema::CheckConstexprFunctionDefinition(clang::FunctionDecl const*, 
clang::Sema::CheckConstexprKind)  
workspace/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:1766:0
#14  clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)  
workspace/llvm-project/clang/lib/Sema/SemaDecl.cpp:14357:9
#15  clang::Parser::ParseFunctionStatementBody(clang::Decl*, 
clang::Parser::ParseScope&)  
workspace/llvm-project/clang/lib/Parse/ParseStmt.cpp:2213:18
```

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: rsmith, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D77041

Added: 
    clang/test/SemaCXX/invalid-constructor-init.cpp

Modified: 
    clang/lib/AST/ExprConstant.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9ebde22f7a58..628f22ae2053 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4976,6 +4976,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
     return false;
   }
 
+  if (const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(Definition)) 
{
+    for (const auto *InitExpr : CtorDecl->inits()) {
+      if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
+        return false;
+    }
+  }
+
   // Can we evaluate this function call?
   if (Definition && Definition->isConstexpr() && Body)
     return true;
@@ -14709,6 +14716,15 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl 
*FD,
   if (FD->isDependentContext())
     return true;
 
+  // Bail out if a constexpr constructor has an initializer that contains an
+  // error. We deliberately don't produce a diagnostic, as we have produced a
+  // relevant diagnostic when parsing the error initializer.
+  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) {
+    for (const auto *InitExpr : Ctor->inits()) {
+      if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
+        return false;
+    }
+  }
   Expr::EvalStatus Status;
   Status.Diag = &Diags;
 

diff  --git a/clang/test/SemaCXX/invalid-constructor-init.cpp 
b/clang/test/SemaCXX/invalid-constructor-init.cpp
new file mode 100644
index 000000000000..8fda9cc525ba
--- /dev/null
+++ b/clang/test/SemaCXX/invalid-constructor-init.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -frecovery-ast -verify %s
+
+struct X {
+  int Y;
+  constexpr X() // expected-error {{constexpr constructor never produces}}
+      : Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}}
+};
+// no crash on evaluating the constexpr ctor.
+constexpr int Z = X().Y; // expected-error {{constexpr variable 'Z' must be 
initialized by a constant expression}}
+
+struct X2 {
+  int Y = foo();    // expected-error {{use of undeclared identifier 'foo'}} \
+                 // expected-note {{subexpression not valid in a constant 
expression}}
+  constexpr X2() {} // expected-error {{constexpr constructor never produces a 
constant expression}}
+};
+
+struct CycleDelegate {
+  int Y;
+  CycleDelegate(int)
+      : Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}}
+  // no bogus "delegation cycle" diagnostic
+  CycleDelegate(float) : CycleDelegate(1) {}
+};


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to