https://github.com/MitalAshok created 
https://github.com/llvm/llvm-project/pull/91894

Also support redeclaring now-constexpr builtins without constexpr

>From 56aed689dc5825fc5bacc6dfdff58ee0eaf71f82 Mon Sep 17 00:00:00 2001
From: Mital Ashok <mi...@mitalashok.co.uk>
Date: Sun, 12 May 2024 19:48:24 +0100
Subject: [PATCH] [Clang] Add attribute for consteval builtins; Declare
 constexpr builtins as constexpr in C++

Also support redeclaring now-constexpr builtins without constexpr
---
 clang/include/clang/Basic/Builtins.h      |  5 +++++
 clang/include/clang/Basic/BuiltinsBase.td |  2 ++
 clang/lib/Sema/SemaDecl.cpp               | 15 +++++++++++----
 clang/lib/Sema/SemaDeclCXX.cpp            | 18 +++++++++++++-----
 clang/lib/Sema/SemaExpr.cpp               |  8 ++++++--
 clang/test/Sema/builtin-redecl.cpp        | 15 ++++++++++-----
 6 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index f955d21169556..e85ec5b2dca14 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -280,6 +280,11 @@ class Context {
     return strchr(getRecord(ID).Attributes, 'E') != nullptr;
   }
 
+  /// Returns true if this is an immediate (consteval) function
+  bool isImmediate(unsigned ID) const {
+    return strchr(getRecord(ID).Attributes, 'G') != nullptr;
+  }
+
 private:
   const Info &getRecord(unsigned ID) const;
 
diff --git a/clang/include/clang/Basic/BuiltinsBase.td 
b/clang/include/clang/Basic/BuiltinsBase.td
index 724747ec76d73..1196b9e15c10d 100644
--- a/clang/include/clang/Basic/BuiltinsBase.td
+++ b/clang/include/clang/Basic/BuiltinsBase.td
@@ -70,6 +70,8 @@ class VScanfFormat<int I> : IndexedAttribute<"S", I>;
 
 // Builtin can be constant evaluated
 def Constexpr : Attribute<"E">;
+// Builtin is immediate and must be constant evaluated. Implies Constexpr.
+def Consteval : Attribute<"EG">;
 
 // Builtin kinds
 // =============
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fb913034bd836..6b0a04585928a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2409,10 +2409,17 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
     Parent = CLinkageDecl;
   }
 
-  FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-                                           /*TInfo=*/nullptr, SC_Extern,
-                                           
getCurFPFeatures().isFPConstrained(),
-                                           false, Type->isFunctionProtoType());
+  ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified;
+  if (getLangOpts().CPlusPlus && Context.BuiltinInfo.isConstantEvaluated(ID)) {
+    ConstexprKind = ConstexprSpecKind::Constexpr;
+    if (Context.BuiltinInfo.isImmediate(ID))
+      ConstexprKind = ConstexprSpecKind::Consteval;
+  }
+
+  FunctionDecl *New = FunctionDecl::Create(
+      Context, Parent, Loc, Loc, II, Type, /*TInfo=*/nullptr, SC_Extern,
+      getCurFPFeatures().isFPConstrained(), /*isInlineSpecified=*/false,
+      Type->isFunctionProtoType(), ConstexprKind);
   New->setImplicit();
   New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 53238d355ea09..1b558d70f9b48 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -676,11 +676,19 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, 
FunctionDecl *Old,
   // template has a constexpr specifier then all its declarations shall
   // contain the constexpr specifier.
   if (New->getConstexprKind() != Old->getConstexprKind()) {
-    Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
-        << New << static_cast<int>(New->getConstexprKind())
-        << static_cast<int>(Old->getConstexprKind());
-    Diag(Old->getLocation(), diag::note_previous_declaration);
-    Invalid = true;
+    if (Old->getBuiltinID() &&
+        Old->getConstexprKind() == ConstexprSpecKind::Constexpr &&
+        New->getConstexprKind() == ConstexprSpecKind::Unspecified) {
+      // Except allow redeclaring a builtin as non-constexpr to match C
+      // redeclarations which will not be constexpr
+      New->setConstexprKind(ConstexprSpecKind::Constexpr);
+    } else {
+      Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
+          << New << static_cast<int>(New->getConstexprKind())
+          << static_cast<int>(Old->getConstexprKind());
+      Diag(Old->getLocation(), diag::note_previous_declaration);
+      Invalid = true;
+    }
   } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
              Old->isDefined(Def) &&
              // If a friend function is inlined but does not have 'inline'
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bb4b116fd73ca..39aa32526d2b1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7095,8 +7095,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
   }
 
   // Bail out early if calling a builtin with custom type checking.
-  if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
-    return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
+  if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
+    ExprResult E = CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
+    if (!E.isInvalid() && Context.BuiltinInfo.isImmediate(BuiltinID))
+      E = CheckForImmediateInvocation(E, FDecl);
+    return E;
+  }
 
   if (getLangOpts().CUDA) {
     if (Config) {
diff --git a/clang/test/Sema/builtin-redecl.cpp 
b/clang/test/Sema/builtin-redecl.cpp
index 323c63e202883..31409a4d46a65 100644
--- a/clang/test/Sema/builtin-redecl.cpp
+++ b/clang/test/Sema/builtin-redecl.cpp
@@ -14,13 +14,18 @@ void __builtin_va_copy(double d);
 // expected-error@+2 {{cannot redeclare builtin function '__builtin_va_end'}}
 // expected-note@+1 {{'__builtin_va_end' is a builtin with type}}
 void __builtin_va_end(__builtin_va_list);
-// RUN: %clang_cc1 %s -fsyntax-only -verify 
-// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
 
 void __va_start(__builtin_va_list*, ...);
 
+          void *__builtin_assume_aligned(const void *, size_t, ...);
 #ifdef __cplusplus
-void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
-#else
-void *__builtin_assume_aligned(const void *, size_t, ...);
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...);
+          void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) noexcept;
+          void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+constexpr void *__builtin_assume_aligned(const void *, size_t, ...) throw();
+
+// expected-error@+1 {{constexpr declaration of '__builtin_calloc' follows 
non-constexpr declaration}}
+constexpr void *__builtin_calloc(size_t, size_t);
+// expected-note@-1 {{previous declaration is here}}
 #endif

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

Reply via email to