hokein created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
hokein edited the summary of this revision.
hokein added inline comments.
hokein added a reviewer: sammccall.


================
Comment at: clang/lib/Sema/SemaDecl.cpp:14359
+        !ErrorsInCtorInitializer &&
         !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose))
       FD->setInvalidDecl();
----------------
The crash is in `CheckConstexprFunctionDefinition`, I tried different ways to 
fixing it:

1) mark `FD` invalid when there are any errors in CtorInitailizer -- clang 
deliberately treats CtorDecl as valid even there are some errors in the 
initializer to prevent spurious diagnostics (see the cycle delegation in the 
test as an example), so marking them invalid may affect the quality of 
diagnostics;

2) Fixing it inside `CheckConstexprFunctionDefinition` or 
`isPotentialConstantExpr`, but it doesn't seem to be a right layer, these 
functions are expected to be called on a validDecl (or at least after a few 
sanity checks), and emit diagnostics.


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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77041

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/invalid-constructor-init.cpp


Index: clang/test/SemaCXX/invalid-constructor-init.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/invalid-constructor-init.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -frecovery-ast -verify %s
+
+struct X {
+  int Y;
+  constexpr X() : Y(foo()) {} // expected-error {{use of undeclared identifier 
'foo'}}
+};
+
+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 "delegation cycle" diagnostic emitted!
+  CycleDelegate(float) : CycleDelegate(1) {}
+};
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -1685,6 +1685,7 @@
 // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
 bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
                                             CheckConstexprKind Kind) {
+  assert(!NewFD->isInvalidDecl());
   const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
   if (MD && MD->isInstance()) {
     // C++11 [dcl.constexpr]p4:
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -45,6 +45,7 @@
 #include "clang/Sema/Template.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Support/Casting.h"
 #include <algorithm>
 #include <cstring>
 #include <functional>
@@ -14345,7 +14346,16 @@
       ActivePolicy = &WP;
     }
 
+    bool ErrorsInCtorInitializer =
+        llvm::isa_and_nonnull<CXXConstructorDecl>(FD)
+            ? llvm::any_of(llvm::dyn_cast<CXXConstructorDecl>(FD)->inits(),
+                           [](const auto *Init) {
+                             return Init->getInit() &&
+                                    Init->getInit()->containsErrors();
+                           })
+            : false;
     if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
+        !ErrorsInCtorInitializer &&
         !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose))
       FD->setInvalidDecl();
 


Index: clang/test/SemaCXX/invalid-constructor-init.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/invalid-constructor-init.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -frecovery-ast -verify %s
+
+struct X {
+  int Y;
+  constexpr X() : Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}}
+};
+
+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 "delegation cycle" diagnostic emitted!
+  CycleDelegate(float) : CycleDelegate(1) {}
+};
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -1685,6 +1685,7 @@
 // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
 bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
                                             CheckConstexprKind Kind) {
+  assert(!NewFD->isInvalidDecl());
   const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
   if (MD && MD->isInstance()) {
     // C++11 [dcl.constexpr]p4:
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -45,6 +45,7 @@
 #include "clang/Sema/Template.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Support/Casting.h"
 #include <algorithm>
 #include <cstring>
 #include <functional>
@@ -14345,7 +14346,16 @@
       ActivePolicy = &WP;
     }
 
+    bool ErrorsInCtorInitializer =
+        llvm::isa_and_nonnull<CXXConstructorDecl>(FD)
+            ? llvm::any_of(llvm::dyn_cast<CXXConstructorDecl>(FD)->inits(),
+                           [](const auto *Init) {
+                             return Init->getInit() &&
+                                    Init->getInit()->containsErrors();
+                           })
+            : false;
     if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
+        !ErrorsInCtorInitializer &&
         !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose))
       FD->setInvalidDecl();
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to