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

Reland: [clang] fix P3310 overload resolution flag propagation #125791

Merged

Conversation

mizvekov
Copy link
Contributor

@mizvekov mizvekov commented Feb 5, 2025

Class templates might be only instantiated when they are required to be complete, but checking the template args against the primary template is immediate.

This result is cached so that later when the class is instantiated, checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon checking against the primary template, so it needs to be cached in the specialziation as well.

This fixes a bug which has not been in any release, so there are no release notes.

Fixes #125290

Class templates might be only instantiated when they are required
to be complete, but checking the template args against the primary
template is immediate.

This result is cached so that later when the class is instantiated,
checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon
checking against the primary template, so it needs to be cached
in the specialziation as well.

This fixes a bug which has not been in any release, so there are no
release notes.

Fixes #125290
@mizvekov mizvekov self-assigned this Feb 5, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category lldb clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Feb 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 5, 2025

@llvm/pr-subscribers-lldb
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Matheus Izvekov (mizvekov)

Changes

Class templates might be only instantiated when they are required to be complete, but checking the template args against the primary template is immediate.

This result is cached so that later when the class is instantiated, checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon checking against the primary template, so it needs to be cached in the specialziation as well.

This fixes a bug which has not been in any release, so there are no release notes.

Fixes #125290


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

16 Files Affected:

  • (modified) clang/include/clang/AST/DeclTemplate.h (+14-2)
  • (modified) clang/include/clang/Sema/Sema.h (+2-2)
  • (modified) clang/lib/AST/ASTImporter.cpp (+3-3)
  • (modified) clang/lib/AST/DeclTemplate.cpp (+24-23)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+5)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+4-1)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+5-3)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (-2)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+1-1)
  • (modified) clang/lib/Sema/SemaType.cpp (+2-1)
  • (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+1)
  • (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+1)
  • (modified) clang/test/AST/ast-dump-templates.cpp (+6045-2)
  • (modified) clang/test/AST/gen_ast_dump_json_test.py (+17-4)
  • (modified) clang/test/SemaTemplate/cwg2398.cpp (+17)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp (+2-1)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 9ecff2c898acd5..03c43765206b18 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1841,15 +1841,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
   LLVM_PREFERRED_TYPE(TemplateSpecializationKind)
   unsigned SpecializationKind : 3;
 
+  /// Indicate that we have matched a parameter pack with a non pack
+  /// argument, when the opposite match is also allowed (strict pack match).
+  /// This needs to be cached as deduction is performed during declaration,
+  /// and we need the information to be preserved so that it is consistent
+  /// during instantiation.
+  bool MatchedPackOnParmToNonPackOnArg : 1;
+
 protected:
   ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
                                   DeclContext *DC, SourceLocation StartLoc,
                                   SourceLocation IdLoc,
                                   ClassTemplateDecl *SpecializedTemplate,
                                   ArrayRef<TemplateArgument> Args,
+                                  bool MatchedPackOnParmToNonPackOnArg,
                                   ClassTemplateSpecializationDecl *PrevDecl);
 
-  explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
+  ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
 
 public:
   friend class ASTDeclReader;
@@ -1859,7 +1867,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
   Create(ASTContext &Context, TagKind TK, DeclContext *DC,
          SourceLocation StartLoc, SourceLocation IdLoc,
          ClassTemplateDecl *SpecializedTemplate,
-         ArrayRef<TemplateArgument> Args,
+         ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
          ClassTemplateSpecializationDecl *PrevDecl);
   static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
                                                              GlobalDeclID ID);
@@ -1930,6 +1938,10 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
     SpecializationKind = TSK;
   }
 
+  bool hasMatchedPackOnParmToNonPackOnArg() const {
+    return MatchedPackOnParmToNonPackOnArg;
+  }
+
   /// Get the point of instantiation (if any), or null if none.
   SourceLocation getPointOfInstantiation() const {
     return PointOfInstantiation;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 472a0e25adc975..79bf6c04ee4969 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13493,8 +13493,8 @@ class Sema final : public SemaBase {
   bool InstantiateClassTemplateSpecialization(
       SourceLocation PointOfInstantiation,
       ClassTemplateSpecializationDecl *ClassTemplateSpec,
-      TemplateSpecializationKind TSK, bool Complain = true,
-      bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false);
+      TemplateSpecializationKind TSK, bool Complain,
+      bool PrimaryHasMatchedPackOnParmToNonPackOnArg);
 
   /// Instantiates the definitions of all of the member
   /// of the given class, which is an instantiation of a class template
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index c9f2f905d2134c..1057f09deda073 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6321,9 +6321,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
     updateLookupTableForTemplateParameters(*ToTPList);
   } else { // Not a partial specialization.
     if (GetImportedOrCreateDecl(
-            D2, D, Importer.getToContext(), D->getTagKind(), DC,
-            *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs,
-            PrevDecl))
+            D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
+            *IdLocOrErr, ClassTemplate, TemplateArgs,
+            D->hasMatchedPackOnParmToNonPackOnArg(), PrevDecl))
       return D2;
 
     // Update InsertPos, because preceding import calls may have invalidated
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 2e1ed9e10713a8..fe8734d262a961 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -957,18 +957,20 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
 // ClassTemplateSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
 
-ClassTemplateSpecializationDecl::
-ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
-                                DeclContext *DC, SourceLocation StartLoc,
-                                SourceLocation IdLoc,
-                                ClassTemplateDecl *SpecializedTemplate,
-                                ArrayRef<TemplateArgument> Args,
-                                ClassTemplateSpecializationDecl *PrevDecl)
+ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
+    ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
+    SourceLocation StartLoc, SourceLocation IdLoc,
+    ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
+    bool MatchedPackOnParmToNonPackOnArg,
+    ClassTemplateSpecializationDecl *PrevDecl)
     : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
                     SpecializedTemplate->getIdentifier(), PrevDecl),
-    SpecializedTemplate(SpecializedTemplate),
-    TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
-    SpecializationKind(TSK_Undeclared) {
+      SpecializedTemplate(SpecializedTemplate),
+      TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
+      SpecializationKind(TSK_Undeclared),
+      MatchedPackOnParmToNonPackOnArg(MatchedPackOnParmToNonPackOnArg) {
+  assert(DK == Kind::ClassTemplateSpecialization ||
+         MatchedPackOnParmToNonPackOnArg == false);
 }
 
 ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
@@ -977,18 +979,14 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
                     SourceLocation(), nullptr, nullptr),
       SpecializationKind(TSK_Undeclared) {}
 
-ClassTemplateSpecializationDecl *
-ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
-                                        DeclContext *DC,
-                                        SourceLocation StartLoc,
-                                        SourceLocation IdLoc,
-                                        ClassTemplateDecl *SpecializedTemplate,
-                                        ArrayRef<TemplateArgument> Args,
-                                   ClassTemplateSpecializationDecl *PrevDecl) {
-  auto *Result =
-      new (Context, DC) ClassTemplateSpecializationDecl(
-          Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
-          SpecializedTemplate, Args, PrevDecl);
+ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
+    ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
+    SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
+    ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
+    ClassTemplateSpecializationDecl *PrevDecl) {
+  auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
+      Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
+      SpecializedTemplate, Args, MatchedPackOnParmToNonPackOnArg, PrevDecl);
   Result->setMayHaveOutOfDateDef(false);
 
   // If the template decl is incomplete, copy the external lexical storage from
@@ -1175,7 +1173,10 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
     ClassTemplatePartialSpecializationDecl *PrevDecl)
     : ClassTemplateSpecializationDecl(
           Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
-          SpecializedTemplate, Args, PrevDecl),
+          // Tracking MatchedPackOnParmToNonPackOnArg for Partial
+          // Specializations is not needed.
+          SpecializedTemplate, Args, /*MatchedPackOnParmToNonPackOnArg=*/false,
+          PrevDecl),
       TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
   if (AdoptTemplateParameterList(Params, this))
     setInvalidDecl();
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 36ef1fc8c79db0..4ab0e7cb5815b6 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -1003,6 +1003,11 @@ void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
 void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
   VisitRecordDecl(RD);
 
+  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+    if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
+      JOS.attribute("strict-pack-match", true);
+  }
+
   // All other information requires a complete definition.
   if (!RD->isCompleteDefinition())
     return;
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index a57cba95974822..7f5a825b687983 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -2525,8 +2525,11 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
     OS << " instantiated_from";
     dumpPointer(Instance);
   }
-  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
+  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
     dumpTemplateSpecializationKind(CTSD->getSpecializationKind());
+    if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
+      OS << " strict-pack-match";
+  }
 
   dumpNestedNameSpecifier(D->getQualifier());
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 35ece88c603ddd..f180be2c1a5e15 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3651,7 +3651,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
           ClassTemplate->getDeclContext(),
           ClassTemplate->getTemplatedDecl()->getBeginLoc(),
           ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted,
-          nullptr);
+          CTAI.MatchedPackOnParmToNonPackOnArg, nullptr);
       ClassTemplate->AddSpecialization(Decl, InsertPos);
       if (ClassTemplate->isOutOfLine())
         Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -8526,7 +8526,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     // this explicit specialization or friend declaration.
     Specialization = ClassTemplateSpecializationDecl::Create(
         Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate,
-        CTAI.CanonicalConverted, PrevDecl);
+        CTAI.CanonicalConverted, CTAI.MatchedPackOnParmToNonPackOnArg,
+        PrevDecl);
     Specialization->setTemplateArgsAsWritten(TemplateArgs);
     SetNestedNameSpecifier(*this, Specialization, SS);
     if (TemplateParameterLists.size() > 0) {
@@ -9869,7 +9870,8 @@ DeclResult Sema::ActOnExplicitInstantiation(
     // this explicit specialization.
     Specialization = ClassTemplateSpecializationDecl::Create(
         Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
-        ClassTemplate, CTAI.CanonicalConverted, PrevDecl);
+        ClassTemplate, CTAI.CanonicalConverted,
+        CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
     SetNestedNameSpecifier(*this, Specialization, SS);
 
     // A MSInheritanceAttr attached to the previous declaration must be
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 137942f0c30bfe..425c41f0f62367 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3341,8 +3341,6 @@ FinishTemplateArgumentDeduction(
     return ConstraintsNotSatisfied
                ? TemplateDeductionResult::ConstraintsNotSatisfied
                : TemplateDeductionResult::SubstitutionFailure;
-  if (InstCTAI.MatchedPackOnParmToNonPackOnArg)
-    Info.setMatchedPackOnParmToNonPackOnArg();
 
   TemplateParameterList *TemplateParams = Template->getTemplateParameters();
   for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4855e8a23689ce..31611695eba7e4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4038,7 +4038,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
       ClassTemplateSpecializationDecl::Create(
           SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
           D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted,
-          PrevDecl);
+          CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
   InstD->setTemplateArgsAsWritten(InstTemplateArgs);
 
   // Add this partial specialization to the set of class template partial
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 33d5378944ddbf..58c72e2ac8935c 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9397,7 +9397,8 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
         runWithSufficientStackSpace(Loc, [&] {
           Diagnosed = InstantiateClassTemplateSpecialization(
               Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
-              /*Complain=*/Diagnoser);
+              /*Complain=*/Diagnoser,
+              ClassTemplateSpec->hasMatchedPackOnParmToNonPackOnArg());
         });
         Instantiated = true;
       }
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 8210eb2143acf5..963122160ff4d0 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2532,6 +2532,7 @@ RedeclarableResult ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
   D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
   D->PointOfInstantiation = readSourceLocation();
   D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
+  D->MatchedPackOnParmToNonPackOnArg = Record.readBool();
 
   bool writtenAsCanonicalDecl = Record.readInt();
   if (writtenAsCanonicalDecl) {
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index fa2294da95de8d..3505db441e829e 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1843,6 +1843,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
   Record.AddTemplateArgumentList(&D->getTemplateArgs());
   Record.AddSourceLocation(D->getPointOfInstantiation());
   Record.push_back(D->getSpecializationKind());
+  Record.push_back(D->hasMatchedPackOnParmToNonPackOnArg());
   Record.push_back(D->isCanonicalDecl());
 
   if (D->isCanonicalDecl()) {
diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp
index 9fcafbcbcc46b6..86af8c50f3174e 100644
--- a/clang/test/AST/ast-dump-templates.cpp
+++ b/clang/test/AST/ast-dump-templates.cpp
@@ -1,7 +1,15 @@
-// RUN: %clang_cc1 -std=c++1z -ast-print %s > %t
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump=json %s | FileCheck --check-prefix=JSON %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-print %s > %t
 // RUN: FileCheck < %t %s -check-prefix=CHECK1
 // RUN: FileCheck < %t %s -check-prefix=CHECK2
-// RUN: %clang_cc1 -std=c++1z -ast-dump %s | FileCheck --check-prefix=DUMP %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck --check-prefix=DUMP %s
+
+// Test with serialization:
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -x c++ -std=c++17 -include-pch %t \
+// RUN: -ast-dump-all /dev/null \
+// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
+// RUN: | FileCheck --strict-whitespace --check-prefix=DUMP %s
 
 template <int X, typename Y, int Z = 5>
 struct foo {
@@ -118,3 +126,6038 @@ void func() {
 // DUMP-NEXT:     `-TemplateTypeParm {{.*}} 'Key'
 }
 }
+
+namespace test7 {
+  template <template<class> class TT> struct A {};
+  template <class...> class B {};
+  template struct A<B>;
+// DUMP-LABEL: NamespaceDecl {{.*}} test7{{$}}
+// DUMP:       ClassTemplateSpecializationDecl {{.*}} struct A definition explicit_instantiation_definition strict-pack-match{{$}}
+} // namespce test7
+
+// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
+
+
+// JSON-NOT: {{^}}Dumping
+// JSON:  "kind": "TranslationUnitDecl",
+// JSON-NEXT:  "loc": {},
+// JSON-NEXT:  "range": {
+// JSON-NEXT:   "begin": {},
+// JSON-NEXT:   "end": {}
+// JSON-NEXT:  },
+// JSON-NEXT:  "inner": [
+// JSON-NEXT:   {
+// JSON-NEXT:    "id": "0x{{.*}}",
+// JSON-NEXT:    "kind": "TypedefDecl",
+// JSON-NEXT:    "loc": {},
+// JSON-NEXT:    "range": {
+// JSON-NEXT:     "begin": {},
+// JSON-NEXT:     "end": {}
+// JSON-NEXT:    },
+// JSON-NEXT:    "isImplicit": true,
+// JSON-NEXT:    "name": "__int128_t",
+// JSON-NEXT:    "type": {
+// JSON-NEXT:     "qualType": "__int128"
+// JSON-NEXT:    },
+// JSON-NEXT:    "inner": [
+// JSON-NEXT:     {
+// JSON-NEXT:      "id": "0x{{.*}}",
+// JSON-NEXT:      "kind": "BuiltinType",
+// JSON-NEXT:      "type": {
+// JSON-NEXT:       "qualType": "__int128"
+// JSON-NEXT:      }
+// JSON-NEXT:     }
+// JSON-NEXT:    ]
+// JSON-NEXT:   },
+// JSON-NEXT:   {
+// JSON-NEXT:    "id": "0x{{.*}}",
+// JSON-NEXT:    "kind": "TypedefDecl",
+// JSON-NEXT:    "loc": {},
+// JSON-NEXT:    "range": {
+// JSON-NEXT:     "begin": {},
+// JSON-NEXT:     "end": {}
+// JSON-NEXT:    },
+// JSON-NEXT:    "isImplicit": true,
+// JSON-NEXT:    "name": "__uint128_t",
+// JSON-NEXT:    "type": {
+// JSON-NEXT:     "qualType": "unsigned __int128"
+// JSON-NEXT:    },
+// JSON-NEXT:    "inner": [
+// JSON-NEXT:     {
+// JSON-NEXT:      "id": "0x{{.*}}",
+// JSON-NEXT:      "kind": "BuiltinType",
+// JSON-NEXT:      "type": {
+// JSON-NEXT:       "qualType": "unsigned __int128"
+// JSON-NEXT:      }
+// JSON-NEXT:     }
+// JSON-NEXT:    ]
+// JSON-NEXT:   },
+// JSON-NEXT:   {
+// JSON-NEXT:    "id": "0x{{.*}}",
+// JSON-NEXT:    "kind": "TypedefDecl",
+// JSON-NEXT:    "loc": {},
+// JSON-NEXT:    "range": {
+// JSON-NEXT:     "begin": {},
+// JSON-NEXT:     "end": {}
+// JSON-NEXT:    },
+// JSON-NEXT:    "isImplicit": true,
+// JSON-NEXT:    "name": "__NSConstantString",
+// JSON-NEXT:    "type": {
+// JSON-NEXT:     "qualType": "__NSConstantString_tag"
+// JSON-NEXT:    },
+// JSON-NEXT:    "inner": [
+// JSON-NEXT:     {
+// JSON-NEXT:      "id": "0x{{.*}}",
+// JSON-NEXT:      "kind": "RecordType",
+// JSON-NEXT:      "type": {
+// JSON-NEXT:       "qualType": "__NSConstantString_tag"
+// JSON-NEXT:      },
+// JSON-NEXT:      "decl": {
+// JSON-NEXT:       "id": "0x{{.*}}",
+// JSON-NEXT:       "kind": "CXXRecordDecl",
+// JSON-NEXT:       "name": "__NSConstantString_tag"
+// JSON-NEXT:      }
+// JSON-NEXT:     }
+// JSON-NEXT:    ]
+// JSON-NEXT:   },
+// JSON-NEXT:   {
+// JSON-NEXT:    "id": "0x{{.*}}",
+// JSON-NEXT:    "kind": "TypedefDecl",
+// JSON-NEXT:    "loc": {},
+// JSON-NEXT:    "range": {
+// JSON-NEXT:     "begin": {},
+// JSON-NEXT:     "end": {}
+// JSON-NEXT:    },
+// JSON-NEXT:    "isImplicit": true,
+// JSON-NEXT:    "name": "__builtin_ms_va_list",
+// JSON-NEXT:    "type": {
+// JSON-NEXT:     "qualType": "char *"
+// JSON-NEXT:    },
+// JSON-NEXT:    "inner": [
+// JSON-NEXT:     {
+// JSON-NEXT:      "id": "0x{{.*}}",
+// JSON-NEXT:      "kind": "PointerType",
+// JSON-NEXT:      "type": {
+// JSON-NEXT:       "qualType": "char *"
+// JSON-NEXT:      },
+// JSON-NEXT:      "inner": [
+// JSON-NEXT:       {
+// JSON-NEXT:        "id": "0x{{.*}}",
+// JSON-NEXT:        "kind": "BuiltinType",
+// JSON-NEXT:        "type": {
+// JSON-NEXT:         "qualType": "char"
+// JSON-NEXT:        }
+// JSON-NEXT:       }
+// JSON-NEXT:      ]
+// JSON-NEXT:     }
+// JSON-NEXT:    ]
+// JSON-NEXT:   },
+// JSON-NEXT:   {
+// JSON-NEXT:    "id": "0x{{.*}}",
+// JSON-NEXT:    "kind": "TypedefDecl",
+// JSON-NEXT:    "loc": {},
+// JSON-NEXT:    "range": {
+// JSON-NEXT:     "begin": {},
+// JSON-NEXT:     "end": {}
+// JSON-NEXT:    },
+// JSON-NEXT:    "isIm...
[truncated]

@cor3ntin
Copy link
Contributor

cor3ntin commented Feb 5, 2025

Initially reverted by #125710
@mizvekov did you do a stage2 build of lldb?

@mizvekov
Copy link
Contributor Author

mizvekov commented Feb 5, 2025

Initially reverted by #125710

@mizvekov did you do a stage2 build of lldb?

Of course.

@mizvekov mizvekov merged commit 08bda1c into main Feb 5, 2025
13 checks passed
@mizvekov mizvekov deleted the users/mizvekov/clang-fix-P3310-strict-match-incomplete-types branch February 5, 2025 15:02
@hokein
Copy link
Collaborator

hokein commented Feb 6, 2025

Heads-up: this patch triggers a MSAN failure in lldb tests (e.g. lldb/test/API/commands/expression/call-function/TestCallStdStringFunction.py), the stacktrace:

==5633==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 in decltype(auto) clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>::operator()<clang::ASTContext&, clang::TagTypeKind, clang::DeclContext*&, clang::SourceLocation&, clang::SourceLocation&, clang::ClassTemplateDecl*&, llvm::SmallVector<clang::TemplateArgument, 2u>&, bool, clang::ClassTemplateSpecializationDecl*&>(clang::ASTContext&, clang::TagTypeKind&&, clang::DeclContext*&, clang::SourceLocation&, clang::SourceLocation&, clang::ClassTemplateDecl*&, llvm::SmallVector<clang::TemplateArgument, 2u>&, bool&&, clang::ClassTemplateSpecializationDecl*&) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:234:16
    #1 in bool clang::ASTNodeImporter::GetImportedOrCreateSpecialDecl<clang::ClassTemplateSpecializationDecl, clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>, clang::ClassTemplateSpecializationDecl, clang::ASTContext&, clang::TagTypeKind, clang::DeclContext*&, clang::SourceLocation&, clang::SourceLocation&, clang::ClassTemplateDecl*&, llvm::SmallVector<clang::TemplateArgument, 2u>&, bool, clang::ClassTemplateSpecializationDecl*&>(clang::ClassTemplateSpecializationDecl*&, clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>, clang::ClassTemplateSpecializationDecl*, clang::ASTContext&, clang::TagTypeKind&&, clang::DeclContext*&, clang::SourceLocation&, clang::SourceLocation&, clang::ClassTemplateDecl*&, llvm::SmallVector<clang::TemplateArgument, 2u>&, bool&&, clang::ClassTemplateSpecializationDecl*&) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:281:13
    #2 in GetImportedOrCreateDecl<clang::ClassTemplateSpecializationDecl, clang::ClassTemplateSpecializationDecl, clang::ASTContext &, clang::TagTypeKind, clang::DeclContext *&, clang::SourceLocation &, clang::SourceLocation &, clang::ClassTemplateDecl *&, llvm::SmallVector<clang::TemplateArgument, 2U> &, bool, clang::ClassTemplateSpecializationDecl *&> llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:251:14
    #3 in clang::ASTNodeImporter::VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:6323:9
    #4 in clang::declvisitor::Base<std::__msan::add_pointer, clang::ASTNodeImporter, llvm::Expected<clang::Decl*>>::Visit(clang::Decl*) llvm/llvm-project/clang/include/clang/AST/DeclNodes.inc
    #5 in clang::ASTImporter::ImportImpl(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9126:19
    #6 in lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl(clang::Decl*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp:1134:23
    #7 in clang::ASTImporter::Import(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9521:27
    #8 in std::__msan::conditional<std::is_base_of_v<clang::Type, clang::RecordDecl>, llvm::Expected<clang::RecordDecl const*>, llvm::Expected<clang::RecordDecl*>>::type clang::ASTNodeImporter::import<clang::RecordDecl>(clang::RecordDecl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:203:31
    #9 in clang::ASTNodeImporter::VisitRecordType(clang::RecordType const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:1559:40
    #10 in clang::TypeVisitor<clang::ASTNodeImporter, llvm::Expected<clang::QualType>>::Visit(clang::Type const*) llvm/llvm-project/clang/include/clang/AST/TypeNodes.inc:76:1
    #11 in clang::ASTImporter::Import(clang::Type const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9157:36
    #12 in clang::ASTImporter::Import(clang::QualType) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9171:31
    #13 in import<clang::QualType> llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:217:23
    #14 in llvm::Expected<clang::TemplateArgument> clang::ASTNodeImporter::import<clang::TemplateArgument>(clang::TemplateArgument const&) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:832:32
    #15 in clang::ASTNodeImporter::ImportTemplateArguments(llvm::ArrayRef<clang::TemplateArgument>, llvm::SmallVectorImpl<clang::TemplateArgument>&) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:2453:24
    #16 in clang::ASTNodeImporter::VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:6219:11
    #17 in clang::declvisitor::Base<std::__msan::add_pointer, clang::ASTNodeImporter, llvm::Expected<clang::Decl*>>::Visit(clang::Decl*) llvm/llvm-project/clang/include/clang/AST/DeclNodes.inc
    #18 in clang::ASTImporter::ImportImpl(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9126:19
    #19 in lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl(clang::Decl*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp:1134:23
    #20 in clang::ASTImporter::Import(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9521:27
    #21 in std::__msan::conditional<std::is_base_of_v<clang::Type, clang::RecordDecl>, llvm::Expected<clang::RecordDecl const*>, llvm::Expected<clang::RecordDecl*>>::type clang::ASTNodeImporter::import<clang::RecordDecl>(clang::RecordDecl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:203:31
    #22 in clang::ASTNodeImporter::VisitRecordType(clang::RecordType const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:1559:40
    #23 in clang::TypeVisitor<clang::ASTNodeImporter, llvm::Expected<clang::QualType>>::Visit(clang::Type const*) llvm/llvm-project/clang/include/clang/AST/TypeNodes.inc:76:1
    #24 in clang::ASTImporter::Import(clang::Type const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9157:36
    #25 in clang::ASTImporter::Import(clang::QualType) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9171:31
    #26 in import<clang::QualType> llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:217:23
    #27 in clang::QualType clang::ASTNodeImporter::importChecked<clang::QualType>(llvm::Error&, clang::QualType const&) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:692:30
    #28 in clang::ASTNodeImporter::VisitTypedefNameDecl(clang::TypedefNameDecl*, bool) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:2823:27
    #29 in VisitTypedefDecl llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:2862:10
    #30 in clang::declvisitor::Base<std::__msan::add_pointer, clang::ASTNodeImporter, llvm::Expected<clang::Decl*>>::Visit(clang::Decl*) llvm/llvm-project/clang/include/clang/AST/DeclNodes.inc:466:1
    #31 in clang::ASTImporter::ImportImpl(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9126:19
    #32 in lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl(clang::Decl*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp:1134:23
    #33 in clang::ASTImporter::Import(clang::Decl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9521:27
    #34 in std::__msan::conditional<std::is_base_of_v<clang::Type, clang::TypedefNameDecl>, llvm::Expected<clang::TypedefNameDecl const*>, llvm::Expected<clang::TypedefNameDecl*>>::type clang::ASTNodeImporter::import<clang::TypedefNameDecl>(clang::TypedefNameDecl*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:203:31
    #35 in clang::ASTNodeImporter::VisitTypedefType(clang::TypedefType const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:1441:45
    #36 in clang::TypeVisitor<clang::ASTNodeImporter, llvm::Expected<clang::QualType>>::Visit(clang::Type const*) llvm/llvm-project/clang/include/clang/AST/TypeNodes.inc:81:1
    #37 in clang::ASTImporter::Import(clang::Type const*) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9157:36
    #38 in clang::ASTImporter::Import(clang::QualType) llvm/llvm-project/clang/lib/AST/ASTImporter.cpp:9171:31
    #39 in lldb_private::ClangASTImporter::CopyType(lldb_private::TypeSystemClang&, lldb_private::CompilerType const&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp:54:56
    #40 in lldb_private::ClangASTSource::GuardedCopyType(lldb_private::CompilerType const&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp:1486:26
    #41 in lldb_private::ClangExpressionDeclMap::GetVariableValue(std::__msan::shared_ptr<lldb_private::Variable>&, lldb_private::Value&, lldb_private::TaggedASTType<1u>*, lldb_private::TaggedASTType<0u>*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp:1513:30
    #42 in lldb_private::ClangExpressionDeclMap::AddOneVariable(lldb_private::NameSearchContext&, std::__msan::shared_ptr<lldb_private::Variable>, std::__msan::shared_ptr<lldb_private::ValueObject>) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp:1654:8
    #43 in lldb_private::ClangExpressionDeclMap::LookupLocalVariable(lldb_private::NameSearchContext&, lldb_private::ConstString, lldb_private::SymbolContext&, lldb_private::CompilerDeclContext const&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp:1094:7
    #44 in lldb_private::ClangExpressionDeclMap::FindExternalVisibleDecls(lldb_private::NameSearchContext&, std::__msan::shared_ptr<lldb_private::Module>, lldb_private::CompilerDeclContext const&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp:1418:9
    #45 in lldb_private::ClangExpressionDeclMap::FindExternalVisibleDecls(lldb_private::NameSearchContext&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp:721:5
    #46 in lldb_private::ClangASTSource::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName, clang::DeclContext const*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp:180:3
    #47 in lldb_private::ClangASTSource::ClangASTSourceProxy::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName, clang::DeclContext const*) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h:219:25
    #48 in clang::DeclContext::lookupImpl(clang::DeclarationName, clang::DeclContext const*) const llvm/llvm-project/clang/lib/AST/DeclBase.cpp:1913:17
    #49 in clang::DeclContext::lookup(clang::DeclarationName) const llvm/llvm-project/clang/lib/AST/DeclBase.cpp:1873:31
    #50 in LookupDirect(clang::Sema&, clang::LookupResult&, clang::DeclContext const*) llvm/llvm-project/clang/lib/Sema/SemaLookup.cpp:1127:39
    #51 in CppNamespaceLookup(clang::Sema&, clang::LookupResult&, clang::ASTContext&, clang::DeclContext const*, (anonymous namespace)::UnqualUsingDirectiveSet&) llvm/llvm-project/clang/lib/Sema/SemaLookup.cpp:1225:16
    #52 in clang::Sema::CppLookupName(clang::LookupResult&, clang::Scope*) llvm/llvm-project/clang/lib/Sema/SemaLookup.cpp:1524:15
    #53 in clang::Sema::LookupName(clang::LookupResult&, clang::Scope*, bool, bool) llvm/llvm-project/clang/lib/Sema/SemaLookup.cpp:2280:9
    #54 in clang::Sema::BuildUsingDeclaration(clang::Scope*, clang::AccessSpecifier, clang::SourceLocation, bool, clang::SourceLocation, clang::CXXScopeSpec&, clang::DeclarationNameInfo, clang::SourceLocation, clang::ParsedAttributesView const&, bool, bool) llvm/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:12832:5
    #55 in clang::Sema::ActOnUsingDeclaration(clang::Scope*, clang::AccessSpecifier, clang::SourceLocation, clang::SourceLocation, clang::CXXScopeSpec&, clang::UnqualifiedId&, clang::SourceLocation, clang::ParsedAttributesView const&) llvm/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:12367:7
    #56 in clang::Parser::ParseUsingDeclaration(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo const&, clang::SourceLocation, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) llvm/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp:899:26
    #57 in clang::Parser::ParseUsingDirectiveOrDeclaration(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo const&, clang::SourceLocation&, clang::ParsedAttributes&) llvm/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp:537:10
    #58 in clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) llvm/llvm-project/clang/lib/Parse/ParseDecl.cpp:2081:12
    #59 in clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&, clang::ParsedAttributes&) llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp
    #60 in clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:125:20
    #61 in clang::Parser::ParseCompoundStatementBody(bool) llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:1267:11
    #62 in clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:2577:21
    #63 in clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) llvm/llvm-project/clang/lib/Parse/Parser.cpp:1520:10
    #64 in clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) llvm/llvm-project/clang/lib/Parse/ParseDecl.cpp
    #65 in clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) llvm/llvm-project/clang/lib/Parse/Parser.cpp:1244:10
    #66 in clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) llvm/llvm-project/clang/lib/Parse/Parser.cpp:1266:12
    #67 in clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) llvm/llvm-project/clang/lib/Parse/Parser.cpp:1069:14
    #68 in clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) llvm/llvm-project/clang/lib/Parse/Parser.cpp:758:12
    #69 in clang::ParseAST(clang::Sema&, bool, bool) llvm/llvm-project/clang/lib/Parse/ParseAST.cpp:171:20
    #70 in lldb_private::ClangExpressionParser::ParseInternal(lldb_private::DiagnosticManager&, clang::CodeCompleteConsumer*, unsigned int, unsigned int) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp:1347:5
    #71 in lldb_private::ClangExpressionParser::Parse(lldb_private::DiagnosticManager&) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp:1204:10
    #72 in lldb_private::ClangUserExpression::TryParse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp:579:35
    #73 in lldb_private::ClangUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) llvm/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp:673:24
    #74 in lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, std::__msan::shared_ptr<lldb_private::ValueObject>&, std::__msan::basic_string<char, std::__msan::char_traits<char>, std::__msan::allocator<char>>*, lldb_private::ValueObject*) llvm/llvm-project/lldb/source/Expression/UserExpression.cpp:280:27
    #75 in lldb_private::Target::EvaluateExpression(llvm::StringRef, lldb_private::ExecutionContextScope*, std::__msan::shared_ptr<lldb_private::ValueObject>&, lldb_private::EvaluateExpressionOptions const&, std::__msan::basic_string<char, std::__msan::char_traits<char>, std::__msan::allocator<char>>*, lldb_private::ValueObject*) llvm/llvm-project/lldb/source/Target/Target.cpp:2853:9
    #76 in lldb_private::CommandObjectExpression::EvaluateExpression(llvm::StringRef, lldb_private::Stream&, lldb_private::Stream&, lldb_private::CommandReturnObject&) llvm/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp:426:38
    #77 in lldb_private::CommandObjectExpression::DoExecute(llvm::StringRef, lldb_private::CommandReturnObject&) llvm/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp:667:7
    #78 in lldb_private::CommandObjectRaw::Execute(char const*, lldb_private::CommandReturnObject&) llvm/llvm-project/lldb/source/Interpreter/CommandObject.cpp:853:7
    #79 in lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, bool) llvm/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp:2085:14

@hokein
Copy link
Collaborator

hokein commented Feb 6, 2025

The msan warning indicates that the StrictPackMatch used here is uninitialized. However, from reading the code, it's unclear to me how this could happen.

So far, I've only observed this failure in lldb tests, which may suggests it might be an LLDB-related issue -- but I don't have enough context on LLDB to say for sure, cc @Michael137.

@Michael137
Copy link
Member

The msan warning indicates that the StrictPackMatch used here is uninitialized. However, from reading the code, it's unclear to me how this could happen.

So far, I've only observed this failure in lldb tests, which may suggests it might be an LLDB-related issue -- but I don't have enough context on LLDB to say for sure, cc @Michael137.

Oh I guess that can happen if we created the decl using CreateDeserialized. In which case the StrictPackMatch would be kept uninitialized. We do that in TypeSystemClang::CreateClassTemplateSpecializationDecl. So we'll have to set it in there to false

@Michael137
Copy link
Member

Michael137 commented Feb 6, 2025

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

@mizvekov
Copy link
Contributor Author

mizvekov commented Feb 6, 2025

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

On the ASTReader, we don't need a setter because it's friends with the class.

I'd worry a little bit about leaving it always set to a fixed value, this could be a hard to track bug in the future for the lldb folks, even if it's probably not observable right now.

@Michael137
Copy link
Member

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

On the ASTReader, we don't need a setter because it's friends with the class.

I'd worry a little bit about leaving it always set to a fixed value, this could be a hard to track bug in the future for the lldb folks, even if it's probably not observable right now.

Yea that's fair. Would you prefer us adding a setter for it then? And set it to a fixed value from LLDB (until we have a better way to deal with it)?

@mizvekov
Copy link
Contributor Author

mizvekov commented Feb 6, 2025

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

On the ASTReader, we don't need a setter because it's friends with the class.

I'd worry a little bit about leaving it always set to a fixed value, this could be a hard to track bug in the future for the lldb folks, even if it's probably not observable right now.

Yea that's fair. Would you prefer us adding a setter for it then? And set it to a fixed value from LLDB (until we have a better way to deal with it)?

Sure, a setter is fine for me. I am not sure from what data you are populating the decl, but if it's like the ast import case, you can forward the flag from the original decl.

If it's being formed from matching as-written template arguments, you can forward the result from CheckTemplateArgument.

Otherwise if it's fully synthetic, I guess you can leave a comment explaining it.

@Michael137
Copy link
Member

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

On the ASTReader, we don't need a setter because it's friends with the class.

I'd worry a little bit about leaving it always set to a fixed value, this could be a hard to track bug in the future for the lldb folks, even if it's probably not observable right now.

Yea that's fair. Would you prefer us adding a setter for it then? And set it to a fixed value from LLDB (until we have a better way to deal with it)?

Sure, a setter is fine for me. I am not sure from what data you are populating the decl, but if it's like the ast import case, you can forward the flag from the original decl.

If it's being formed from matching as-written template arguments, you can forward the result from CheckTemplateArgument.

Otherwise if it's fully synthetic, I guess you can leave a comment explaining it.

Yea we're creating it from debug-info. Haven't thought about whether we can infer this field from debug-info, but either way, I'll go the setter approach then, thanks!

@mizvekov
Copy link
Contributor Author

mizvekov commented Feb 6, 2025

Actually, @mizvekov, can we make the ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, Kind DK) constructor default initialize the StrictPackMatch member to false? In that case users of CreateDeserialized wouldn't need to worry about it being potentially uninitialized? Otherwise we'll have to expose a setter and call it from LLDB

On the ASTReader, we don't need a setter because it's friends with the class.

I'd worry a little bit about leaving it always set to a fixed value, this could be a hard to track bug in the future for the lldb folks, even if it's probably not observable right now.

Yea that's fair. Would you prefer us adding a setter for it then? And set it to a fixed value from LLDB (until we have a better way to deal with it)?

Sure, a setter is fine for me. I am not sure from what data you are populating the decl, but if it's like the ast import case, you can forward the flag from the original decl.

If it's being formed from matching as-written template arguments, you can forward the result from CheckTemplateArgument.

Otherwise if it's fully synthetic, I guess you can leave a comment explaining it.

Yea we're creating it from debug-info. Haven't thought about whether we can infer this field from debug-info, but either way, I'll go the setter approach then, thanks!

I see. It looks like you would need to call CheckTemplateArgument with the arguments you get from debug info anyway, otherwise some things wouldn't work, like pack parameters.

You can use the result from this call to get the value for the flag. Otherwise if you don't currently check the arguments, you could leave a FIXME.

Michael137 added a commit to Michael137/llvm-project that referenced this pull request Feb 7, 2025
…StrictPackMatch field

This addresses the MSAN failure reported
in llvm#125791 (comment):
```
==5633==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 in clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>::operator()
    llvm#1 in bool clang::ASTNodeImporter::GetImportedOrCreateSpecialDecl<...>
...
```

The ASTImporter reads `D->hasStrictPackMatch()` and forwards it to the constructor of the destination `ClassTemplateSpecializationDecl`. But if `D` is a decl that LLDB created from debug-info, it would've been created using `ClassTemplateSpecializationDecl::CreateDeserialized`, which doesn't initialize the `StrictPackMatch` field.

This patch just initializes the field to a fixed value of `false`, to preserve previous behaviour and avoid the use-of-uninitialized-value.

An alternative would be to always initialize it in the `ClassTemplateSpecializationDecl` constructor, but there were reservations about providing a default value for it because it might lead to hard-to-diagnose problems down the line.
@Michael137
Copy link
Member

Put up #126215
Should address the failure @hokein observed

Michael137 added a commit that referenced this pull request Feb 7, 2025
…StrictPackMatch field (#126215)

This addresses the MSAN failure reported
in
#125791 (comment):
```
==5633==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 in clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>::operator()
    #1 in bool clang::ASTNodeImporter::GetImportedOrCreateSpecialDecl<...>
...
```

The ASTImporter reads `D->hasStrictPackMatch()` and forwards it to the
constructor of the destination `ClassTemplateSpecializationDecl`. But if
`D` is a decl that LLDB created from debug-info, it would've been
created using `ClassTemplateSpecializationDecl::CreateDeserialized`,
which doesn't initialize the `StrictPackMatch` field.

This patch just initializes the field to a fixed value of `false`, to
preserve previous behaviour and avoid the use-of-uninitialized-value.

An alternative would be to always initialize it in the
`ClassTemplateSpecializationDecl` constructor, but there were
reservations about providing a default value for it because it might
lead to hard-to-diagnose problems down the line.
github-actions bot pushed a commit to arm/arm-toolchain that referenced this pull request Feb 7, 2025
…tionDecl's StrictPackMatch field (#126215)

This addresses the MSAN failure reported
in
llvm/llvm-project#125791 (comment):
```
==5633==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 in clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>::operator()
    #1 in bool clang::ASTNodeImporter::GetImportedOrCreateSpecialDecl<...>
...
```

The ASTImporter reads `D->hasStrictPackMatch()` and forwards it to the
constructor of the destination `ClassTemplateSpecializationDecl`. But if
`D` is a decl that LLDB created from debug-info, it would've been
created using `ClassTemplateSpecializationDecl::CreateDeserialized`,
which doesn't initialize the `StrictPackMatch` field.

This patch just initializes the field to a fixed value of `false`, to
preserve previous behaviour and avoid the use-of-uninitialized-value.

An alternative would be to always initialize it in the
`ClassTemplateSpecializationDecl` constructor, but there were
reservations about providing a default value for it because it might
lead to hard-to-diagnose problems down the line.
@mizvekov mizvekov added this to the LLVM 20.X Release milestone Feb 7, 2025
Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Feb 11, 2025
…125791)

Class templates might be only instantiated when they are required to be
complete, but checking the template args against the primary template is
immediate.

This result is cached so that later when the class is instantiated,
checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon
checking against the primary template, so it needs to be cached in the
specialziation as well.

This fixes a bug which has not been in any release, so there are no
release notes.

Fixes llvm#125290
Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Feb 11, 2025
…StrictPackMatch field (llvm#126215)

This addresses the MSAN failure reported
in
llvm#125791 (comment):
```
==5633==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 in clang::ASTNodeImporter::CallOverloadedCreateFun<clang::ClassTemplateSpecializationDecl>::operator()
    llvm#1 in bool clang::ASTNodeImporter::GetImportedOrCreateSpecialDecl<...>
...
```

The ASTImporter reads `D->hasStrictPackMatch()` and forwards it to the
constructor of the destination `ClassTemplateSpecializationDecl`. But if
`D` is a decl that LLDB created from debug-info, it would've been
created using `ClassTemplateSpecializationDecl::CreateDeserialized`,
which doesn't initialize the `StrictPackMatch` field.

This patch just initializes the field to a fixed value of `false`, to
preserve previous behaviour and avoid the use-of-uninitialized-value.

An alternative would be to always initialize it in the
`ClassTemplateSpecializationDecl` constructor, but there were
reservations about providing a default value for it because it might
lead to hard-to-diagnose problems down the line.
@mizvekov
Copy link
Contributor Author

/cherry-pick 08bda1c

@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2025

/pull-request #127779

mizvekov added a commit that referenced this pull request Feb 19, 2025
…5791)

Class templates might be only instantiated when they are required to be
complete, but checking the template args against the primary template is
immediate.

This result is cached so that later when the class is instantiated,
checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon
checking against the primary template, so it needs to be cached in the
specialziation as well.

This fixes a bug which has not been in any release, so there are no
release notes.

Fixes #125290
swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 20, 2025
…m#125791)

Class templates might be only instantiated when they are required to be
complete, but checking the template args against the primary template is
immediate.

This result is cached so that later when the class is instantiated,
checking against the primary template is not repeated.

The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon
checking against the primary template, so it needs to be cached in the
specialziation as well.

This fixes a bug which has not been in any release, so there are no
release notes.

Fixes llvm#125290
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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 lldb
Projects
Development

Successfully merging this pull request may close these issues.

Possible bug in implementation of P3310
6 participants