Tyker updated this revision to Diff 298818.
Tyker marked 9 inline comments as done.
Tyker added a comment.

addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D74130

Files:
  clang/include/clang/AST/Expr.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/ScopeInfo.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -258,6 +258,26 @@
   return f(0);  
 };
 
+consteval int f1() {
+// expected-note@-1+ {{declared here}}
+  return 0;
+}
+consteval auto g() { return f1; }
+consteval int h(int (*p)() = g()) { return p(); }
+int h1(int (*p)() = g()) { return p(); }
+// expected-error@-1 {{is not a constant expression}}
+// expected-note@-2 {{pointer to a consteval}}
+
+constexpr auto e = g();
+// expected-error@-1 {{call to consteval function}}
+// expected-note@-2 {{is not a constant expression}}
+
+auto l = [](int (*p)() = g()) { return p(); };
+// expected-error@-1 {{is not a constant expression}}
+// expected-note@-2 {{pointer to a consteval}}
+
+auto l2 = [](int (*p)() = g()) consteval { return p(); };
+
 }
 
 namespace std {
@@ -594,3 +614,42 @@
 }
 
 } // namespace special_ctor
+
+namespace top_level {
+struct S {
+  consteval S() {}
+  int a;
+// expected-note@-1 {{subobject declared here}}
+};
+
+S s; // expected-error {{is not a constant expression}}
+// expected-note@-1 {{is not initialized}}
+
+struct S1 {
+  consteval S1() {}
+  int a = 0;
+};
+
+S1 s1;
+
+}
+
+namespace unevaluated {
+struct N {
+  constexpr N() {}
+  N(N const&) = delete;
+};
+template <typename T> constexpr void bad_assert_copyable() { T t; T t2 = t; }
+using ineffective = decltype(bad_assert_copyable<N>());
+
+template <typename T> consteval void assert_copyable() { T t; T t2 = t; }
+using check = decltype(assert_copyable<N>());
+}
+
+// namespace error {
+
+// consteval void check(bool b) { if (!b) throw; }
+// constinit int x = true ? 1 : (check(false), 2);
+// constinit int x1 = (check(false), 2);
+
+// }
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -891,6 +891,16 @@
   LambdaScopeInfo *const LSI = getCurLambda();
   assert(LSI && "LambdaScopeInfo should be on stack!");
 
+  /// If the lambda is consteval the paramters will be evaluated in constant
+  /// context immediate invocations don't need to be kept.
+  if (ParamInfo.getDeclSpec().getConstexprSpecifier() != CSK_consteval) {
+    ExprEvalContexts.back().ReferenceToConsteval.insert(
+        LSI->ReferenceToConsteval.begin(), LSI->ReferenceToConsteval.end());
+    ExprEvalContexts.back().ImmediateInvocationCandidates.append(
+        LSI->ImmediateInvocationCandidates.begin(),
+        LSI->ImmediateInvocationCandidates.end());
+  }
+
   // Determine if we're within a context where we know that the lambda will
   // be dependent, because there are template parameters in scope.
   bool KnownDependent;
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -16183,7 +16183,7 @@
 
 ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
   if (!E.isUsable() || !Decl || !Decl->isConsteval() || isConstantEvaluated() ||
-      RebuildingImmediateInvocation)
+      RebuildingImmediateInvocation || isUnevaluatedContext())
     return E;
 
   /// Opportunistically remove the callee from ReferencesToConsteval if we can.
@@ -16229,6 +16229,7 @@
     SemaRef.Diag(CE->getBeginLoc(), diag::err_invalid_consteval_call) << FD;
     for (auto &Note : Notes)
       SemaRef.Diag(Note.first, Note.second);
+    CE->markFailed();
     return;
   }
   CE->MoveIntoResult(Eval.Val, SemaRef.getASTContext());
@@ -16312,13 +16313,25 @@
   It->getPointer()->setSubExpr(Res.get());
 }
 
-static void
-HandleImmediateInvocations(Sema &SemaRef,
-                           Sema::ExpressionEvaluationContextRecord &Rec) {
+void Sema::HandleImmediateInvocations(
+    Sema::ExpressionEvaluationContextRecord &Rec) {
   if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
        Rec.ReferenceToConsteval.size() == 0) ||
-      SemaRef.RebuildingImmediateInvocation)
+      RebuildingImmediateInvocation || isUnevaluatedContext())
+    return;
+
+  /// If the scope is lambda params we don't know wether the lambda is consteval
+  /// yet. So we store all the needed information in the lambda and resolve it
+  /// later.
+  if (Rec.ExprContext ==
+      Sema::ExpressionEvaluationContextRecord::EK_LambdaParam) {
+    getCurLambda()->ImmediateInvocationCandidates.append(
+        Rec.ImmediateInvocationCandidates.begin(),
+        Rec.ImmediateInvocationCandidates.end());
+    getCurLambda()->ReferenceToConsteval.insert(
+        Rec.ReferenceToConsteval.begin(), Rec.ReferenceToConsteval.end());
     return;
+  }
 
   /// When we have more then 1 ImmediateInvocationCandidates we need to check
   /// for nested ImmediateInvocationCandidates. when we have only 1 we only
@@ -16327,16 +16340,16 @@
 
     /// Prevent sema calls during the tree transform from adding pointers that
     /// are already in the sets.
-    llvm::SaveAndRestore<bool> DisableIITracking(
-        SemaRef.RebuildingImmediateInvocation, true);
+    llvm::SaveAndRestore<bool> DisableIITracking(RebuildingImmediateInvocation,
+                                                 true);
 
     /// Prevent diagnostic during tree transfrom as they are duplicates
-    Sema::TentativeAnalysisScope DisableDiag(SemaRef);
+    Sema::TentativeAnalysisScope DisableDiag(*this);
 
     for (auto It = Rec.ImmediateInvocationCandidates.rbegin();
          It != Rec.ImmediateInvocationCandidates.rend(); It++)
       if (!It->getInt())
-        RemoveNestedImmediateInvocation(SemaRef, Rec, It);
+        RemoveNestedImmediateInvocation(*this, Rec, It);
   } else if (Rec.ImmediateInvocationCandidates.size() == 1 &&
              Rec.ReferenceToConsteval.size()) {
     struct SimpleRemove : RecursiveASTVisitor<SimpleRemove> {
@@ -16351,13 +16364,12 @@
         Rec.ImmediateInvocationCandidates.front().getPointer()->getSubExpr());
   }
   for (auto CE : Rec.ImmediateInvocationCandidates)
-    if (!CE.getInt())
-      EvaluateAndDiagnoseImmediateInvocation(SemaRef, CE);
+    if (!CE.getInt() && !CE.getPointer()->hasAPValueResult())
+      EvaluateAndDiagnoseImmediateInvocation(*this, CE);
   for (auto DR : Rec.ReferenceToConsteval) {
     auto *FD = cast<FunctionDecl>(DR->getDecl());
-    SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address)
-        << FD;
-    SemaRef.Diag(FD->getLocation(), diag::note_declared_at);
+    Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address) << FD;
+    Diag(FD->getLocation(), diag::note_declared_at);
   }
 }
 
@@ -16394,7 +16406,7 @@
   }
 
   WarnOnPendingNoDerefs(Rec);
-  HandleImmediateInvocations(*this, Rec);
+  HandleImmediateInvocations(Rec);
 
   // Warn on any volatile-qualified simple-assignments that are not discarded-
   // value expressions nor unevaluated operands (those cases get removed from
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1023,6 +1023,8 @@
   DiagnoseUnterminatedPragmaPack();
   DiagnoseUnterminatedPragmaAttribute();
 
+  HandleImmediateInvocations(ExprEvalContexts.back());
+
   // All delayed member exception specs should be checked or we end up accepting
   // incompatible declarations.
   assert(DelayedOverridingExceptionSpecChecks.empty());
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6455,8 +6455,9 @@
     ProhibitAttributes(FnAttrs);
   } else {
     if (Tok.isNot(tok::r_paren))
-      ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo,
-                                      EllipsisLoc);
+      ParseParameterDeclarationClause(
+          D.getContext(), FirstArgAttrs, ParamInfo, EllipsisLoc,
+          D.getDeclSpec().getConstexprSpecifier() == CSK_consteval);
     else if (RequiresArg)
       Diag(Tok, diag::err_argument_required_after_attribute);
 
@@ -6705,10 +6706,9 @@
 /// [C++11] attribute-specifier-seq parameter-declaration
 ///
 void Parser::ParseParameterDeclarationClause(
-       DeclaratorContext DeclaratorCtx,
-       ParsedAttributes &FirstArgAttrs,
-       SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
-       SourceLocation &EllipsisLoc) {
+    DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs,
+    SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
+    SourceLocation &EllipsisLoc, bool InConstantContext) {
 
   // Avoid exceeding the maximum function scope depth.
   // See https://bugs.llvm.org/show_bug.cgi?id=19607
@@ -6859,8 +6859,14 @@
           // used.
           EnterExpressionEvaluationContext Eval(
               Actions,
-              Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,
-              Param);
+              InConstantContext
+                  ? Sema::ExpressionEvaluationContext::ConstantEvaluated
+                  : Sema::ExpressionEvaluationContext::
+                        PotentiallyEvaluatedIfUsed,
+              Param,
+              DeclaratorCtx == DeclaratorContext::LambdaExprContext
+                  ? Sema::ExpressionEvaluationContextRecord::EK_LambdaParam
+                  : Sema::ExpressionEvaluationContextRecord::EK_Other);
 
           ExprResult DefArgResult;
           if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -1185,7 +1185,10 @@
     /// \brief Describes whether we are in an expression constext which we have
     /// to handle differently.
     enum ExpressionKind {
-      EK_Decltype, EK_TemplateArgument, EK_Other
+      EK_Decltype,
+      EK_TemplateArgument,
+      EK_LambdaParam,
+      EK_Other
     } ExprContext;
 
     ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
@@ -2414,6 +2417,8 @@
                                      bool &AddToScope);
   bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
 
+  void HandleImmediateInvocations(Sema::ExpressionEvaluationContextRecord &Rec);
+
   enum class CheckConstexprKind {
     /// Diagnose issues that are non-constant or that are extensions.
     Diagnose,
Index: clang/include/clang/Sema/ScopeInfo.h
===================================================================
--- clang/include/clang/Sema/ScopeInfo.h
+++ clang/include/clang/Sema/ScopeInfo.h
@@ -881,6 +881,14 @@
 
   SourceLocation PotentialThisCaptureLocation;
 
+  /// Set of candidates for starting an immediate invocation.
+  llvm::SmallVector<llvm::PointerIntPair<ConstantExpr *, 1>, 2>
+      ImmediateInvocationCandidates;
+
+  /// Set of DeclRefExprs referencing a consteval function when used in a
+  /// context not already known to be immediately invoked.
+  llvm::SmallPtrSet<DeclRefExpr *, 2> ReferenceToConsteval;
+
   LambdaScopeInfo(DiagnosticsEngine &Diag)
       : CapturingScopeInfo(Diag, ImpCap_None) {
     Kind = SK_Lambda;
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2923,10 +2923,9 @@
          Declarator &D,
          SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
   void ParseParameterDeclarationClause(
-         DeclaratorContext DeclaratorContext,
-         ParsedAttributes &attrs,
-         SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
-         SourceLocation &EllipsisLoc);
+      DeclaratorContext DeclaratorContext, ParsedAttributes &attrs,
+      SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
+      SourceLocation &EllipsisLoc, bool InConstantContext = false);
   void ParseBracketDeclarator(Declarator &D);
   void ParseMisplacedBracketDeclarator(Declarator &D);
 
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -1066,6 +1066,8 @@
     return SubExpr->getEndLoc();
   }
 
+  void markFailed() { setDependence(ExprDependence::Error); }
+
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == ConstantExprClass;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D74130: [... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D741... Tyker via Phabricator via cfe-commits
    • [PATCH] D741... Tyker via Phabricator via cfe-commits
    • [PATCH] D741... Richard Smith - zygoloid via Phabricator via cfe-commits

Reply via email to