erichkeane updated this revision to Diff 344813.
erichkeane added a comment.

Moved `IfStmt`/discarded case logic to ExprEvaluatorBase per @rsmith 's 
suggestion.  This is the 'highest' in the tree that has a `Sema`/`ASTContext` 
reference, so anything 'higher' in the tree would be higher touch. @rsmith: 
WDYT?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102251/new/

https://reviews.llvm.org/D102251

Files:
  clang/include/clang/AST/EvaluatedExprVisitor.h
  clang/include/clang/AST/Stmt.h
  clang/lib/AST/Stmt.cpp
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCUDA/deferred-diags.cu

Index: clang/test/SemaCUDA/deferred-diags.cu
===================================================================
--- clang/test/SemaCUDA/deferred-diags.cu
+++ clang/test/SemaCUDA/deferred-diags.cu
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fcuda-is-device -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fcuda-is-device -fsyntax-only -std=c++17 -verify %s
 
 #include "Inputs/cuda.h"
 
@@ -8,29 +8,55 @@
   // expected-error@-1 2{{cannot use 'throw' in __host__ __device__ function}}
 }
 
+inline __host__ __device__ void hasInvalid2() {
+  throw NULL;
+  // expected-error@-1 2{{cannot use 'throw' in __host__ __device__ function}}
+}
+
+inline __host__ __device__ void hasInvalidDiscarded() {
+  // This is only used in the discarded statements below, so this should not diagnose.
+  throw NULL;
+}
+
 static __device__ void use0() {
   hasInvalid(); // expected-note {{called by 'use0'}}
   hasInvalid(); // expected-note {{called by 'use0'}}
+
+  if constexpr (true) {
+    hasInvalid2(); // expected-note {{called by 'use0'}}
+  } else {
+    hasInvalidDiscarded();
+  }
+
+  if constexpr (false) {
+    hasInvalidDiscarded();
+  } else {
+    hasInvalid2(); // expected-note {{called by 'use0'}}
+  }
+
+  if constexpr (false) {
+    hasInvalidDiscarded();
+  }
 }
 
 // To avoid excessive diagnostic messages, deferred diagnostics are only
 // emitted the first time a function is called.
 static __device__ void use1() {
-  use0(); // expected-note 2{{called by 'use1'}}
+  use0(); // expected-note 4{{called by 'use1'}}
   use0();
 }
 
 static __device__ void use2() {
-  use1(); // expected-note 2{{called by 'use2'}}
+  use1(); // expected-note 4{{called by 'use2'}}
   use1();
 }
 
 static __device__ void use3() {
-  use2(); // expected-note 2{{called by 'use3'}}
+  use2(); // expected-note 4{{called by 'use3'}}
   use2();
 }
 
 __global__ void use4() {
-  use3(); // expected-note 2{{called by 'use4'}}
+  use3(); // expected-note 4{{called by 'use4'}}
   use3();
 }
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1569,6 +1569,8 @@
   DeferredDiagnosticsEmitter(Sema &S)
       : Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {}
 
+  bool shouldVisitDiscardedCase() const { return false; }
+
   void VisitOMPTargetDirective(OMPTargetDirective *Node) {
     ++InOMPDeviceContext;
     Inherited::VisitOMPTargetDirective(Node);
Index: clang/lib/AST/Stmt.cpp
===================================================================
--- clang/lib/AST/Stmt.cpp
+++ clang/lib/AST/Stmt.cpp
@@ -989,12 +989,20 @@
   return isa<ObjCAvailabilityCheckExpr>(getCond());
 }
 
-Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
+Optional<Stmt *> IfStmt::getNondiscardedCase(const ASTContext &Ctx) {
   if (!isConstexpr() || getCond()->isValueDependent())
     return None;
   return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen();
 }
 
+Optional<const Stmt *>
+IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
+  if (Optional<Stmt *> Result =
+          const_cast<IfStmt *>(this)->getNondiscardedCase(Ctx))
+    return *Result;
+  return None;
+}
+
 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
                  Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
                  SourceLocation RP)
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -2080,6 +2080,7 @@
   /// If this is an 'if constexpr', determine which substatement will be taken.
   /// Otherwise, or if the condition is value-dependent, returns None.
   Optional<const Stmt*> getNondiscardedCase(const ASTContext &Ctx) const;
+  Optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx);
 
   bool isObjCAvailabilityCheck() const;
 
Index: clang/include/clang/AST/EvaluatedExprVisitor.h
===================================================================
--- clang/include/clang/AST/EvaluatedExprVisitor.h
+++ clang/include/clang/AST/EvaluatedExprVisitor.h
@@ -32,6 +32,9 @@
   const ASTContext &Context;
 
 public:
+  // Return whether this visitor should recurse into discarded statements for a
+  // 'constexpr-if'.
+  bool shouldVisitDiscardedCase() const { return true; }
 #define PTR(CLASS) typename Ptr<CLASS>::type
 
   explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { }
@@ -83,7 +86,7 @@
 
   void VisitCallExpr(PTR(CallExpr) CE) {
     if (!CE->isUnevaluatedBuiltinCall(Context))
-      return static_cast<ImplClass*>(this)->VisitExpr(CE);
+      return getDerived().VisitExpr(CE);
   }
 
   void VisitLambdaExpr(PTR(LambdaExpr) LE) {
@@ -103,6 +106,20 @@
         this->Visit(SubStmt);
   }
 
+  void VisitIfStmt(PTR(IfStmt) If) {
+    if (!getDerived().shouldVisitDiscardedCase()) {
+      if (auto SubStmt = If->getNondiscardedCase(Context)) {
+        if (*SubStmt)
+          this->Visit(*SubStmt);
+        return;
+      }
+    }
+
+    getDerived().VisitStmt(If);
+  }
+
+  ImplClass &getDerived() { return *static_cast<ImplClass *>(this); }
+
 #undef PTR
 };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to