Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. #78041

Merged
merged 1 commit into from
Jan 21, 2024

Conversation

bolshakov-a
Copy link
Contributor

Previously committed as 9e08e51, and reverted because a dependency commit was reverted, then committed again as 4b57400 and reverted again because "dependency commit" 5a391d3 was reverted. But it doesn't seem that 5a391d3 was a real dependency for this.

This commit incorporates 4b57400 and 18e093f by Richard Smith (@zygoloid), with some minor fixes, most notably:

  • UncommonValue renamed to StructuralValue

  • VK_PRValue instead of VK_RValue as default kind in lvalue and member pointer handling branch in BuildExpressionFromNonTypeTemplateArgumentValue;

  • handling of StructuralValue in IsTypeDeclaredInsideVisitor;

  • filling in SugaredConverted along with CanonicalConverted parameter in Sema::CheckTemplateArgument;

  • minor cleanup in TemplateInstantiator::transformNonTypeTemplateParmRef;

  • TemplateArgument constructors refactored;

  • ODRHash calculation for UncommonValue;

  • USR generation for UncommonValue;

  • more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143);

  • IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context;

  • noundef attribute and opaque pointers in template-arguments test;

  • analysis for C++17 mode is turned off for templates in warn-bool-conversion test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and BuildExpressionFromNonTypeTemplateArgumentValue makes OpaqueValueExpr for it, and DiagnoseAlwaysNonNullPointer cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace if by if constexpr;

  • temp.arg.nontype/p1.cpp and dr18xx.cpp tests fixed.

@llvmbot llvmbot added clang Clang issues not falling into any other category lldb clangd clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:codegen debuginfo labels Jan 13, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 13, 2024

@llvm/pr-subscribers-clang-tools-extra
@llvm/pr-subscribers-clangd
@llvm/pr-subscribers-clang-modules
@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-debuginfo
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-lldb

Author: Andrey Ali Khan Bolshakov (bolshakov-a)

Changes

Previously committed as 9e08e51, and reverted because a dependency commit was reverted, then committed again as 4b57400 and reverted again because "dependency commit" 5a391d3 was reverted. But it doesn't seem that 5a391d3 was a real dependency for this.

This commit incorporates 4b57400 and 18e093f by Richard Smith (@zygoloid), with some minor fixes, most notably:

  • UncommonValue renamed to StructuralValue

  • VK_PRValue instead of VK_RValue as default kind in lvalue and member pointer handling branch in BuildExpressionFromNonTypeTemplateArgumentValue;

  • handling of StructuralValue in IsTypeDeclaredInsideVisitor;

  • filling in SugaredConverted along with CanonicalConverted parameter in Sema::CheckTemplateArgument;

  • minor cleanup in TemplateInstantiator::transformNonTypeTemplateParmRef;

  • TemplateArgument constructors refactored;

  • ODRHash calculation for UncommonValue;

  • USR generation for UncommonValue;

  • more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143);

  • IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context;

  • noundef attribute and opaque pointers in template-arguments test;

  • analysis for C++17 mode is turned off for templates in warn-bool-conversion test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and BuildExpressionFromNonTypeTemplateArgumentValue makes OpaqueValueExpr for it, and DiagnoseAlwaysNonNullPointer cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace if by if constexpr;

  • temp.arg.nontype/p1.cpp and dr18xx.cpp tests fixed.


Patch is 101.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/78041.diff

47 Files Affected:

  • (modified) clang-tools-extra/clangd/DumpAST.cpp (+1)
  • (modified) clang-tools-extra/clangd/FindTarget.cpp (+1)
  • (modified) clang/docs/ReleaseNotes.rst (+2)
  • (modified) clang/include/clang/AST/ODRHash.h (+3)
  • (modified) clang/include/clang/AST/PropertiesBase.td (+14)
  • (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+2)
  • (modified) clang/include/clang/AST/TemplateArgumentVisitor.h (+2)
  • (modified) clang/include/clang/AST/TemplateBase.h (+55-31)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (-5)
  • (modified) clang/include/clang/Sema/Sema.h (+2-2)
  • (modified) clang/lib/AST/ASTContext.cpp (+5)
  • (modified) clang/lib/AST/ASTImporter.cpp (+13)
  • (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+4)
  • (modified) clang/lib/AST/Decl.cpp (+4)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+37-2)
  • (modified) clang/lib/AST/MicrosoftMangle.cpp (+62-16)
  • (modified) clang/lib/AST/ODRHash.cpp (+72)
  • (modified) clang/lib/AST/StmtProfile.cpp (+6)
  • (modified) clang/lib/AST/TemplateBase.cpp (+110-3)
  • (modified) clang/lib/AST/TypeLoc.cpp (+1)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+10)
  • (modified) clang/lib/CodeGen/CGExpr.cpp (+12-3)
  • (modified) clang/lib/Index/USRGeneration.cpp (+10)
  • (modified) clang/lib/Sema/SemaLookup.cpp (+1)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+9-1)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+130-88)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+46-18)
  • (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+6-8)
  • (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+2)
  • (modified) clang/lib/Sema/TreeTransform.h (+10-2)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+1)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+1)
  • (modified) clang/test/CXX/drs/dr18xx.cpp (+2-2)
  • (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+3-1)
  • (modified) clang/test/CodeGenCXX/mangle-ms-templates.cpp (+48)
  • (modified) clang/test/CodeGenCXX/mangle-template.cpp (+39-1)
  • (added) clang/test/CodeGenCXX/template-arguments.cpp (+113)
  • (added) clang/test/Index/USR/structural-value-tpl-arg.cpp (+23)
  • (modified) clang/test/Modules/odr_hash.cpp (+190-3)
  • (modified) clang/test/SemaCXX/warn-bool-conversion.cpp (+2)
  • (modified) clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp (+19-21)
  • (modified) clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp (+22-18)
  • (modified) clang/tools/libclang/CIndex.cpp (+5)
  • (modified) clang/tools/libclang/CXCursor.cpp (+3)
  • (modified) clang/www/cxx_status.html (+13-5)
  • (modified) lldb/include/lldb/lldb-enumerations.h (+1)
  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3)
diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp
index b0cec65c39fa31..9a525efb938e8d 100644
--- a/clang-tools-extra/clangd/DumpAST.cpp
+++ b/clang-tools-extra/clangd/DumpAST.cpp
@@ -143,6 +143,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
       TEMPLATE_ARGUMENT_KIND(Declaration);
       TEMPLATE_ARGUMENT_KIND(Template);
       TEMPLATE_ARGUMENT_KIND(TemplateExpansion);
+      TEMPLATE_ARGUMENT_KIND(StructuralValue);
 #undef TEMPLATE_ARGUMENT_KIND
     }
     llvm_unreachable("Unhandled ArgKind enum");
diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 839cf6332fe8b0..a4a261030d399b 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -1032,6 +1032,7 @@ class ExplicitReferenceCollector
     case TemplateArgument::Pack:
     case TemplateArgument::Type:
     case TemplateArgument::Expression:
+    case TemplateArgument::StructuralValue:
       break; // Handled by VisitType and VisitExpression.
     };
     return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3cbce1be159437..57c444fd95be1b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -180,6 +180,8 @@ C++ Language Changes
 
 C++20 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
+- Implemented `P1907R1 <https://wg21.link/P1907R1>` which extends allowed non-type template argument
+  kinds with e.g. floating point values and pointers and references to subobjects.
 
 C++23 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h
index cedf644520fc32..a1caa6d39a87c3 100644
--- a/clang/include/clang/AST/ODRHash.h
+++ b/clang/include/clang/AST/ODRHash.h
@@ -25,6 +25,7 @@
 
 namespace clang {
 
+class APValue;
 class Decl;
 class IdentifierInfo;
 class NestedNameSpecifier;
@@ -101,6 +102,8 @@ class ODRHash {
   // Save booleans until the end to lower the size of data to process.
   void AddBoolean(bool value);
 
+  void AddStructuralValue(const APValue &);
+
   static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent);
 
 private:
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index d86c4eba6a2251..0270c086d06b6a 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -808,6 +808,20 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
     return TemplateArgument(ctx, value, type, isDefaulted);
   }]>;
 }
+let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in {
+  def : Property<"value", APValue> {
+    let Read = [{ node.getAsStructuralValue() }];
+  }
+  def : Property<"type", QualType> {
+    let Read = [{ node.getStructuralValueType() }];
+  }
+  def : Property<"isDefaulted", Bool> {
+    let Read = [{ node.getIsDefaulted() }];
+  }
+  def : Creator<[{
+    return TemplateArgument(ctx, type, value, isDefaulted);
+  }]>;
+}
 let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
   def : Property<"name", TemplateName> {
     let Read = [{ node.getAsTemplateOrTemplatePattern() }];
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8f2714e142bbe3..2aee6a947141b6 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -850,6 +850,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
+  case TemplateArgument::StructuralValue:
     return true;
 
   case TemplateArgument::Type:
@@ -882,6 +883,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
+  case TemplateArgument::StructuralValue:
     return true;
 
   case TemplateArgument::Type: {
diff --git a/clang/include/clang/AST/TemplateArgumentVisitor.h b/clang/include/clang/AST/TemplateArgumentVisitor.h
index 190aa97adf4551..cf0d3220158063 100644
--- a/clang/include/clang/AST/TemplateArgumentVisitor.h
+++ b/clang/include/clang/AST/TemplateArgumentVisitor.h
@@ -37,6 +37,7 @@ class Base {
       DISPATCH(Declaration);
       DISPATCH(NullPtr);
       DISPATCH(Integral);
+      DISPATCH(StructuralValue);
       DISPATCH(Template);
       DISPATCH(TemplateExpansion);
       DISPATCH(Expression);
@@ -59,6 +60,7 @@ class Base {
   VISIT_METHOD(Declaration);
   VISIT_METHOD(NullPtr);
   VISIT_METHOD(Integral);
+  VISIT_METHOD(StructuralValue);
   VISIT_METHOD(Template);
   VISIT_METHOD(TemplateExpansion);
   VISIT_METHOD(Expression);
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index b7cd71f17c9442..fea2c8ccfee675 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -50,6 +50,7 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
 
 namespace clang {
 
+class APValue;
 class ASTContext;
 class Expr;
 struct PrintingPolicy;
@@ -80,6 +81,13 @@ class TemplateArgument {
     /// that was provided for an integral non-type template parameter.
     Integral,
 
+    /// The template argument is a non-type template argument that can't be
+    /// represented by the special-case Declaration, NullPtr, or Integral
+    /// forms. These values are only ever produced by constant evaluation,
+    /// so cannot be dependent.
+    /// TODO: merge Declaration, NullPtr and Integral into this?
+    StructuralValue,
+
     /// The template argument is a template name that was provided for a
     /// template template parameter.
     Template,
@@ -130,6 +138,14 @@ class TemplateArgument {
     };
     void *Type;
   };
+  struct V {
+    LLVM_PREFERRED_TYPE(ArgKind)
+    unsigned Kind : 31;
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned IsDefaulted : 1;
+    APValue *Value;
+    void *Type;
+  };
   struct A {
     LLVM_PREFERRED_TYPE(ArgKind)
     unsigned Kind : 31;
@@ -156,11 +172,19 @@ class TemplateArgument {
   union {
     struct DA DeclArg;
     struct I Integer;
+    struct V Value;
     struct A Args;
     struct TA TemplateArg;
     struct TV TypeOrValue;
   };
 
+  void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted);
+  void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted);
+  void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value,
+                        QualType Type, bool IsDefaulted);
+  void initFromStructural(const ASTContext &Ctx, QualType Type,
+                          const APValue &V, bool IsDefaulted);
+
 public:
   /// Construct an empty, invalid template argument.
   constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {}
@@ -168,25 +192,22 @@ class TemplateArgument {
   /// Construct a template type argument.
   TemplateArgument(QualType T, bool isNullPtr = false,
                    bool IsDefaulted = false) {
-    TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
-    TypeOrValue.IsDefaulted = IsDefaulted;
-    TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+    initFromType(T, isNullPtr, IsDefaulted);
   }
 
-  /// Construct a template argument that refers to a
-  /// declaration, which is either an external declaration or a
-  /// template declaration.
+  /// Construct a template argument that refers to a (non-dependent)
+  /// declaration.
   TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) {
-    assert(D && "Expected decl");
-    DeclArg.Kind = Declaration;
-    DeclArg.IsDefaulted = IsDefaulted;
-    DeclArg.QT = QT.getAsOpaquePtr();
-    DeclArg.D = D;
+    initFromDeclaration(D, QT, IsDefaulted);
   }
 
   /// Construct an integral constant template argument. The memory to
   /// store the value is allocated with Ctx.
-  TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type,
+  TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
+                   QualType Type, bool IsDefaulted = false);
+
+  /// Construct a template argument from an arbitrary constant value.
+  TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value,
                    bool IsDefaulted = false);
 
   /// Construct an integral constant template argument with the same
@@ -297,7 +318,7 @@ class TemplateArgument {
   /// Retrieve the type for a type template argument.
   QualType getAsType() const {
     assert(getKind() == Type && "Unexpected kind");
-    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
+    return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
   }
 
   /// Retrieve the declaration for a declaration non-type
@@ -315,7 +336,7 @@ class TemplateArgument {
   /// Retrieve the type for null non-type template argument.
   QualType getNullPtrType() const {
     assert(getKind() == NullPtr && "Unexpected kind");
-    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
+    return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
   }
 
   /// Retrieve the template name for a template name argument.
@@ -371,6 +392,14 @@ class TemplateArgument {
   /// default template parameter.
   bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; }
 
+  /// Get the value of a StructuralValue.
+  const APValue &getAsStructuralValue() const { return *Value.Value; }
+
+  /// Get the type of a StructuralValue.
+  QualType getStructuralValueType() const {
+    return QualType::getFromOpaquePtr(Value.Type);
+  }
+
   /// If this is a non-type template argument, get its type. Otherwise,
   /// returns a null QualType.
   QualType getNonTypeTemplateArgumentType() const;
@@ -516,6 +545,7 @@ class TemplateArgumentLoc {
     assert(Argument.getKind() == TemplateArgument::NullPtr ||
            Argument.getKind() == TemplateArgument::Integral ||
            Argument.getKind() == TemplateArgument::Declaration ||
+           Argument.getKind() == TemplateArgument::StructuralValue ||
            Argument.getKind() == TemplateArgument::Expression);
   }
 
@@ -541,13 +571,9 @@ class TemplateArgumentLoc {
   /// - Fetches the full source range of the argument.
   SourceRange getSourceRange() const LLVM_READONLY;
 
-  const TemplateArgument &getArgument() const {
-    return Argument;
-  }
+  const TemplateArgument &getArgument() const { return Argument; }
 
-  TemplateArgumentLocInfo getLocInfo() const {
-    return LocInfo;
-  }
+  TemplateArgumentLocInfo getLocInfo() const { return LocInfo; }
 
   TypeSourceInfo *getTypeSourceInfo() const {
     if (Argument.getKind() != TemplateArgument::Type)
@@ -575,6 +601,11 @@ class TemplateArgumentLoc {
     return LocInfo.getAsExpr();
   }
 
+  Expr *getSourceStructuralValueExpression() const {
+    assert(Argument.getKind() == TemplateArgument::StructuralValue);
+    return LocInfo.getAsExpr();
+  }
+
   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
     if (Argument.getKind() != TemplateArgument::Template &&
         Argument.getKind() != TemplateArgument::TemplateExpansion)
@@ -606,8 +637,7 @@ class TemplateArgumentListInfo {
 public:
   TemplateArgumentListInfo() = default;
 
-  TemplateArgumentListInfo(SourceLocation LAngleLoc,
-                           SourceLocation RAngleLoc)
+  TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc)
       : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
 
   // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
@@ -626,21 +656,15 @@ class TemplateArgumentListInfo {
     return Arguments.data();
   }
 
-  llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
-    return Arguments;
-  }
+  llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; }
 
   const TemplateArgumentLoc &operator[](unsigned I) const {
     return Arguments[I];
   }
 
-  TemplateArgumentLoc &operator[](unsigned I) {
-    return Arguments[I];
-  }
+  TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; }
 
-  void addArgument(const TemplateArgumentLoc &Loc) {
-    Arguments.push_back(Loc);
-  }
+  void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); }
 };
 
 /// Represents an explicit template argument list in C++, e.g.,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a79892e40030a..8c74d12e674624 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5138,8 +5138,6 @@ def err_non_type_template_arg_subobject : Error<
   "non-type template argument refers to subobject '%0'">;
 def err_non_type_template_arg_addr_label_diff : Error<
   "template argument / label address difference / what did you expect?">;
-def err_non_type_template_arg_unsupported : Error<
-  "sorry, non-type template argument of type %0 is not yet supported">;
 def err_template_arg_not_convertible : Error<
   "non-type template argument of type %0 cannot be converted to a value "
   "of type %1">;
@@ -5191,9 +5189,6 @@ def err_template_arg_not_object_or_func : Error<
   "non-type template argument does not refer to an object or function">;
 def err_template_arg_not_pointer_to_member_form : Error<
   "non-type template argument is not a pointer to member constant">;
-def err_template_arg_member_ptr_base_derived_not_supported : Error<
-  "sorry, non-type template argument of pointer-to-member type %1 that refers "
-  "to member %q0 of a different class is not supported yet">;
 def err_template_arg_invalid : Error<
   "non-type template argument '%0' is invalid">;
 def ext_template_arg_extra_parens : ExtWarn<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cf2d4fbe6d3ba1..a3881709263daa 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8569,8 +8569,8 @@ class Sema final {
                                           QualType ParamType,
                                           SourceLocation Loc);
   ExprResult
-  BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
-                                              SourceLocation Loc);
+  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
+                                             SourceLocation Loc);
 
   /// Enumeration describing how template parameter lists are compared
   /// for equality.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d9cefcaa84d7e5..2df986c8541057 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6753,6 +6753,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
     case TemplateArgument::Integral:
       return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
 
+    case TemplateArgument::StructuralValue:
+      return TemplateArgument(*this,
+                              getCanonicalType(Arg.getStructuralValueType()),
+                              Arg.getAsStructuralValue());
+
     case TemplateArgument::Type:
       return TemplateArgument(getCanonicalType(Arg.getAsType()),
                               /*isNullPtr*/ false, Arg.getIsDefaulted());
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index b762d6a4cd3800..8c279dd1eb048b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -823,6 +823,17 @@ ASTNodeImporter::import(const TemplateArgument &From) {
                             From.getIsDefaulted());
   }
 
+  case TemplateArgument::StructuralValue: {
+    ExpectedType ToTypeOrErr = import(From.getStructuralValueType());
+    if (!ToTypeOrErr)
+      return ToTypeOrErr.takeError();
+    Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue());
+    if (!ToValueOrErr)
+      return ToValueOrErr.takeError();
+    return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
+                            *ToValueOrErr);
+  }
+
   case TemplateArgument::Template: {
     Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
     if (!ToTemplateOrErr)
@@ -3572,6 +3583,8 @@ class IsTypeDeclaredInsideVisitor
     case TemplateArgument::NullPtr:
       // FIXME: The type is not allowed to be in the function?
       return CheckType(Arg.getNullPtrType());
+    case TemplateArgument::StructuralValue:
+      return CheckType(Arg.getStructuralValueType());
     case TemplateArgument::Pack:
       for (const auto &PackArg : Arg.getPackAsArray())
         if (checkTemplateArgument(PackArg))
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index a9e0d1698a9178..39a2f7ce61e135 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -628,6 +628,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
                                     Arg2.getAsExpr());
 
+  case TemplateArgument::StructuralValue:
+    // FIXME: Do we need to customize the comparison?
+    return Arg1.structurallyEquals(Arg2);
+
   case TemplateArgument::Pack:
     return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
                                     Arg2.pack_elements());
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index e1440e5183a4e6..a2f50ae4ce8eeb 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -343,6 +343,10 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
       LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
       continue;
 
+    case TemplateArgument::StructuralValue:
+      LV.merge(getLVForValue(Arg.getAsStructuralValue(), computation));
+      continue;
+
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:
       if (TemplateDecl *Template =
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b1678479888eb7..d3ef822b371d5e 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4833,9 +4833,26 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
     E = cast<CXXStdInitializerListExpr>(E)->getSubExpr();
     goto recurse;
 
-  case Expr::SubstNonTypeTemplateParmExprClass:
+  case Expr::SubstNonTypeTemplateParmExprClass: {
+    // Mangle a substituted parameter the same way we mangle the template
+    // argument.
+    auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E);
+    if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) {
+      // Pull out the constant value and mangle it as a template argument.
+      QualType ParamType = SNTTPE->getParameterType(Context.getASTContext());
+      if (CE->hasAPValueResult())
+        mangleValueInTemplateArg(ParamType, CE->getResultAsAPValue(), false,
+                                 /*NeedExactType=*/true);
+      else
+        mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false,
+                                 /*NeedExactType=*/true);
+      break;
+    }
+    // The remaining cases all happen to be substituted with expressions that
+    // mangle the same as a corresponding template argument anyway.
     E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
     goto recurse;
+  }
 
   case Expr::UserDefinedLiteralClass:
     // We follow g++'s approach of mangling a UDL as a call to the literal
@@ -6064,6 +6081,11 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
     mangleNullPointer(A.getNullPtrType());
     break;
   }
+  case TemplateArgument::StructuralValue:
+    mangleValueInTemplateArg(A.getStructuralValueType(),
+                             A.getAsStructuralValue(),
+                             /*TopLevel=*/true, NeedExactType);
+    break;
   case TemplateArgument::Pack: {
     //  <template-arg> ::= J <template-arg>* E
     Out << 'J';
@@ -6472,7 +6494,20 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       Out << "plcvPcad";
       Kind = Offset;
     } else {
-      if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
+      // Clang 11 and before mangled ...
[truncated]

@@ -25,7 +25,7 @@ template <int &> struct S {}; // #dr1801-S
S<i> V; // #dr1801-S-i
// cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}}
// cxx98-14-note@#dr1801-S {{template parameter is declared here}}
// since-cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
// cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this. Here it is stated that this should be ill-formed, with a reference to N4268. But it seems that it is not actual after P1907R1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting P1907R1 wording changes:

For a non-type template-parameter of reference or pointer type <...> the reference or pointer value shall not refer to or be the address of (respectively):
a subobject (6.7.2),
<...>
a subobject (6.7.2) of one of the above.

My reading is that you indeed can reference subobjects in NTTP since 20, unless they fall into one of the narrow categories listed in that paragraph. The change you made is correct, unless P1907R1 was adopted as a DR.

Sorry I forgot to check current wording when I added the test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this restriction no longer exist in the current wording. @zygoloid

@@ -5401,6 +5409,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
// feasible some day.
return TA.getAsIntegral().getBitWidth() <= 64 &&
IsReconstitutableType(TA.getIntegralType());
case TemplateArgument::StructuralValue:
return false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwblaikie, could you verify please? Maybe, non-type template arguments of floating point types are reconstitutable though?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @dwblaikie

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is blocking either way, at worse we have suboptimal debugging experience for a new feature

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delays in the debug info review for this - it is on my list :/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did finally take a look at this - I think the Clang side of things is fine - if anything improvements could be made to LLVM to be able to lower constants to DWARF for a wider variety of values.
eg: For the float example, the IR is:

!8 = !DITemplateValueParameter(name: "F", type: !9, value: float 1.000000e+00)

But the DWARF backend can't handle the float constant - the handling is in DwarfUnit::constructTemplateValueParameterDIE (in llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp) and currently only handles ConstantInt (for basic stuff - bools, ints, etc) and GlobalValue (for pointer non-type template parameters).

So for these new floats and such, the DWARF doesn't include the value, only the type.

GCC uses this encoding, for instance:

0x0000002b:     DW_TAG_template_value_parameter [3]   (0x0000001e)
                  DW_AT_name [DW_FORM_string]   ("F")
                  DW_AT_type [DW_FORM_ref4]     (cu + 0x004d => {0x0000004d} "float")
                  DW_AT_const_value [DW_FORM_block1]    (<0x04> 00 00 80 3f )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying! Probably, I'll come back to this some day to extend the backend, but I'm not sure.

Copy link
Contributor

@Endilll Endilll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ DR test changes look good to me.

@@ -25,7 +25,7 @@ template <int &> struct S {}; // #dr1801-S
S<i> V; // #dr1801-S-i
// cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}}
// cxx98-14-note@#dr1801-S {{template parameter is declared here}}
// since-cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
// cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting P1907R1 wording changes:

For a non-type template-parameter of reference or pointer type <...> the reference or pointer value shall not refer to or be the address of (respectively):
a subobject (6.7.2),
<...>
a subobject (6.7.2) of one of the above.

My reading is that you indeed can reference subobjects in NTTP since 20, unless they fall into one of the narrow categories listed in that paragraph. The change you made is correct, unless P1907R1 was adopted as a DR.

Sorry I forgot to check current wording when I added the test.

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments/nitpicks
Should we add a couple of PCH tests ?

clang/include/clang/AST/TemplateBase.h Show resolved Hide resolved
clang/lib/CodeGen/CGExpr.cpp Outdated Show resolved Hide resolved
@@ -12,6 +12,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/ODRHash.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the header necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ODRHash is used inside the newly added code. Btw, what do you mean by "necessary"? I think one should not rely on transitive #includes in general. (I'm just an active contributor of the IWYU project. Trust me!)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this one looks that it's needed, sorry.

The idea (for the other comments), is that we try to avoid changes in PRs that are not strictly related to the change being made, mostly to avoid conflicts.

If we wanted to follow a IWYU style and reorganize our headers, we would prefer separate PRs or NFC changes (although if we wanted to sort that kind of policy, we would have to do an RFC - again, because that sort of refactor is likely to induce conflicts).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify: do you insist that #include set added in a PR should be minimal for compilability?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't be minimizing the #include set, but it is often a 'red flag' when someone adds one, so Corentin brought it up.

IMO, I have no problem with adding the include here, and a IWYU RFC would be welcomed (and I am less concerned about the 'induce conflicts' as these are touched rarely).

clang/lib/AST/ODRHash.cpp Outdated Show resolved Hide resolved
clang/lib/AST/ASTStructuralEquivalence.cpp Outdated Show resolved Hide resolved
@bolshakov-a
Copy link
Contributor Author

Should we add a couple of PCH tests ?

clang/test/Modules/odr_hash.cpp should cover AST serialization/deserialization. But I could missing something, of course. What is your concern?

@bolshakov-a
Copy link
Contributor Author

Btw, I have a local branch with a few distinct commits. I could temporarily push it to simplify review process, and then squash them before merging.

@cor3ntin
Copy link
Contributor

Should we add a couple of PCH tests ?

clang/test/Modules/odr_hash.cpp should cover AST serialization/deserialization. But I could missing something, of course. What is your concern?

Looking at those tests again, they seem sufficient.

@cor3ntin
Copy link
Contributor

I'm tempted to think that we should accept / merge this now @AaronBallman

The logic is that this is a pretty big hole in our C++20 support and I don't think it's reasonable to try a merge after the deadline for 18. WDYT?

@Endilll
Copy link
Contributor

Endilll commented Jan 15, 2024

The logic is that this is a pretty big hole in our C++20 support and I don't think it's reasonable to try a merge after the deadline for 18. WDYT?

From our past experience with release managers, they seem quite generous with deadlines to merge stuff in, as long as maintainers agree. I think the real question is how much time do we want this to bake in tree before users get to see it.

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love it if @efriedma-quic / @rjmccall looked at the mangling parts, and @dwblaikie looked at the Debug info.

Else, LGTM.

@@ -551,6 +646,18 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
case TemplateArgument::Integral:
return DB << toString(Arg.getAsIntegral(), 10);

case TemplateArgument::StructuralValue: {
// FIXME: We're guessing at LangOptions!
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty unfortunate, but it looks like we're doing this in a few places.

@@ -12,6 +12,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/ODRHash.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't be minimizing the #include set, but it is often a 'red flag' when someone adds one, so Corentin brought it up.

IMO, I have no problem with adding the include here, and a IWYU RFC would be welcomed (and I am less concerned about the 'induce conflicts' as these are touched rarely).

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @rjmccall for Itanium mangling expertise to make sure we're matching the spec.

There are a few merge conflicts that also cropped up which need to be resolved, but overall I think this is pretty close to ready to try to re-land. It would be nice if we could get this in before the Clang 18 branch next Tue if possible (no pressure though).

clang/lib/AST/ItaniumMangle.cpp Outdated Show resolved Hide resolved
clang/lib/AST/ItaniumMangle.cpp Show resolved Hide resolved
@@ -5401,6 +5409,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
// feasible some day.
return TA.getAsIntegral().getBitWidth() <= 64 &&
IsReconstitutableType(TA.getIntegralType());
case TemplateArgument::StructuralValue:
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @dwblaikie

llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Jan 31, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Feb 1, 2024
`OpaqueValueExpr` doesn't necessarily contain a source expression.
Particularly, after llvm#78041, it is used to carry the type and the value
kind of a non-type template argument of floating-point type or referring
to a subobject (those are so called `StructuralValue` arguments).

This fixes llvm#79575.

(cherry picked from commit ef67f63)
@eaeltsin
Copy link
Contributor

eaeltsin commented Feb 2, 2024

#80050 opened. Nevertheless, a reproducer for future work would be appreciated.

I'm running a reduction, but it progresses extremely slowly. Will post as soon as it converges to something meaningful (or I'll get some time to reduce the test case by hand).

llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Feb 4, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Fixes a regression from llvm#78041 as reported in the review.  The original
patch failed to compare the canonical type, which this adds.  A slightly
modified test of the original report is added.

(cherry picked from commit e3ee376)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
`OpaqueValueExpr` doesn't necessarily contain a source expression.
Particularly, after llvm#78041, it is used to carry the type and the value
kind of a non-type template argument of floating-point type or referring
to a subobject (those are so called `StructuralValue` arguments).

This fixes llvm#79575.

(cherry picked from commit ef67f63)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Fixes a regression from llvm#78041 as reported in the review.  The original
patch failed to compare the canonical type, which this adds.  A slightly
modified test of the original report is added.

(cherry picked from commit e3ee376)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
`OpaqueValueExpr` doesn't necessarily contain a source expression.
Particularly, after llvm#78041, it is used to carry the type and the value
kind of a non-type template argument of floating-point type or referring
to a subobject (those are so called `StructuralValue` arguments).

This fixes llvm#79575.

(cherry picked from commit ef67f63)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Fixes a regression from llvm#78041 as reported in the review.  The original
patch failed to compare the canonical type, which this adds.  A slightly
modified test of the original report is added.

(cherry picked from commit e3ee376)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
`OpaqueValueExpr` doesn't necessarily contain a source expression.
Particularly, after llvm#78041, it is used to carry the type and the value
kind of a non-type template argument of floating-point type or referring
to a subobject (those are so called `StructuralValue` arguments).

This fixes llvm#79575.

(cherry picked from commit ef67f63)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Fixes a regression from llvm#78041 as reported in the review.  The original
patch failed to compare the canonical type, which this adds.  A slightly
modified test of the original report is added.

(cherry picked from commit e3ee376)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
`OpaqueValueExpr` doesn't necessarily contain a source expression.
Particularly, after llvm#78041, it is used to carry the type and the value
kind of a non-type template argument of floating-point type or referring
to a subobject (those are so called `StructuralValue` arguments).

This fixes llvm#79575.

(cherry picked from commit ef67f63)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
…#80050)

This returns (probably temporarily) array-referring NTTP behavior to
which was prior to llvm#78041 because ~~I'm fed up~~ have no time to fix
regressions.

(cherry picked from commit 9bf4e54)
bolshakov-a added a commit to bolshakov-a/llvm-project that referenced this pull request Mar 20, 2024
Introduced in llvm#78041, originally reported as llvm#79957 and fixed partially
in llvm#80050.

`OpaqueValueExpr` used with `TemplateArgument::StructuralValue` has no
corresponding source expression.

A test case with subobject-referring NTTP added.
mizvekov added a commit that referenced this pull request May 24, 2024
…he template differ

This was not implemented in #78041

This patch does not implement this fucntionality, it just falls back to the expression
when possible.

Otherwise, such as when dealing with canonical types to begin with,
this will just ignore the argument as if it wasn't even there.

Fixes #93068
@mizvekov
Copy link
Contributor

mizvekov commented May 24, 2024

This missed adding support to StructuralValue template arguments to the template differ.

See #93265

The support is still missing, we are just avoiding the crash for now.

mizvekov added a commit that referenced this pull request May 24, 2024
…he template differ

This was not implemented in #78041

This patch does not implement this fucntionality, it just falls back to the expression
when possible.

Otherwise, such as when dealing with canonical types to begin with,
this will just ignore the argument as if it wasn't even there.

Fixes #93068
mizvekov added a commit that referenced this pull request May 24, 2024
…he template differ (#93265)

This was not implemented in
#78041 when StructuralValue
TemplateArguments were originally added.

This patch does not implement this functionality, it just falls back to
the expression when possible.

Otherwise, such as when dealing with canonical types to begin with, this
will just ignore the argument as if it wasn't even there.

Fixes #93068
efriedma-quic pushed a commit that referenced this pull request May 24, 2024
…#85837)

Introduced in #78041, originally reported as #79957 and fixed partially
in #80050.

`OpaqueValueExpr` used with `TemplateArgument::StructuralValue` has no
corresponding source expression.

A test case with subobject-referring NTTP added.
@shafik
Copy link
Collaborator

shafik commented Oct 14, 2024

This crash is due to this set of changes: #112222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++20 clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category clang-tools-extra clangd debuginfo lldb
Projects
None yet
Development

Successfully merging this pull request may close these issues.