llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: purnima shrivastava (purnima-nlp)

<details>
<summary>Changes</summary>


This PR addresses a compiler crash encountered when handling defaulted 
comparison operators (`operator&lt;=&gt;`) inside a struct.

- Explored the Clang AST and Sema codebase (`clang/lib/AST/Decl.cpp` and 
`clang/lib/Sema/SemaDeclCXX.cpp`) to trace and resolve the underlying recovery 
state handling, added some code too in these files. 
- Added a new regression test 
(`clang/test/SemaCXX/defaulted-compare-recovery-crash.cpp`) to ensure the 
compiler recovers cleanly and emits proper diagnostics instead of crashing.
- issue #<!-- -->210286 

---

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


3 Files Affected:

- (modified) clang/lib/AST/Decl.cpp (+241-251) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+1150-1237) 
- (added) clang/test/SemaCXX/defaulted-compare-recovery-crash.cpp (+16) 


``````````diff
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 4eaef0d87f3e5..825244d79973d 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -79,7 +79,8 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) {
 
 void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
   SourceLocation Loc = this->Loc;
-  if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+  if (!Loc.isValid() && TheDecl)
+    Loc = TheDecl->getLocation();
   if (Loc.isValid()) {
     Loc.print(OS, Context.getSourceManager());
     OS << ": ";
@@ -162,8 +163,7 @@ static bool hasExplicitVisibilityAlready(LVComputationKind 
computation) {
 
 /// Given an LVComputationKind, return one of the same type/value sort
 /// that records that it already has explicit visibility.
-static LVComputationKind
-withExplicitVisibilityAlready(LVComputationKind Kind) {
+static LVComputationKind withExplicitVisibilityAlready(LVComputationKind Kind) 
{
   Kind.IgnoreExplicitVisibility = true;
   return Kind;
 }
@@ -178,8 +178,7 @@ static std::optional<Visibility> 
getExplicitVisibility(const NamedDecl *D,
 /// Is the given declaration a "type" or a "value" for the purposes of
 /// visibility computation?
 static bool usesTypeVisibility(const NamedDecl *D) {
-  return isa<TypeDecl>(D) ||
-         isa<ClassTemplateDecl>(D) ||
+  return isa<TypeDecl>(D) || isa<ClassTemplateDecl>(D) ||
          isa<ObjCInterfaceDecl>(D);
 }
 
@@ -189,7 +188,7 @@ template <class T>
 static std::enable_if_t<!std::is_base_of_v<RedeclarableTemplateDecl, T>, bool>
 isExplicitMemberSpecialization(const T *D) {
   if (const MemberSpecializationInfo *member =
-        D->getMemberSpecializationInfo()) {
+          D->getMemberSpecializationInfo()) {
     return member->isExplicitSpecialization();
   }
   return false;
@@ -204,8 +203,7 @@ static bool isExplicitMemberSpecialization(const 
RedeclarableTemplateDecl *D) {
 
 /// Given a visibility attribute, return the explicit visibility
 /// associated with it.
-template <class T>
-static Visibility getVisibilityFromAttr(const T *attr) {
+template <class T> static Visibility getVisibilityFromAttr(const T *attr) {
   switch (attr->getVisibility()) {
   case T::Default:
     return DefaultVisibility;
@@ -289,8 +287,8 @@ LinkageInfo LinkageComputer::getLVForTemplateParameterList(
     }
 
     // Look at all expansions in an expanded pack.
-    for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
-           i != n; ++i) {
+    for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters(); i != n;
+         ++i) {
       LV.merge(getLVForTemplateParameterList(
           TTP->getExpansionTemplateParameters(i), computation));
     }
@@ -370,8 +368,9 @@ LinkageComputer::getLVForTemplateArgumentList(const 
TemplateArgumentList &TArgs,
   return getLVForTemplateArgumentList(TArgs.asArray(), computation);
 }
 
-static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
-                        const FunctionTemplateSpecializationInfo *specInfo) {
+static bool shouldConsiderTemplateVisibility(
+    const FunctionDecl *fn,
+    const FunctionTemplateSpecializationInfo *specInfo) {
   // Include visibility from the template parameters and arguments
   // only if this is not an explicit instantiation or specialization
   // with direct explicit visibility.  (Implicit instantiations won't
@@ -393,8 +392,7 @@ void LinkageComputer::mergeTemplateLV(
     LinkageInfo &LV, const FunctionDecl *fn,
     const FunctionTemplateSpecializationInfo *specInfo,
     LVComputationKind computation) {
-  bool considerVisibility =
-    shouldConsiderTemplateVisibility(fn, specInfo);
+  bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo);
 
   FunctionTemplateDecl *temp = specInfo->getTemplate();
   // Merge information from the template declaration.
@@ -427,8 +425,8 @@ static bool hasDirectVisibilityAttribute(const NamedDecl *D,
 
 /// Should we consider visibility associated with the template
 /// arguments and parameters of the given class template specialization?
-static bool shouldConsiderTemplateVisibility(
-                                 const ClassTemplateSpecializationDecl *spec,
+static bool
+shouldConsiderTemplateVisibility(const ClassTemplateSpecializationDecl *spec,
                                  LVComputationKind computation) {
   // Include visibility from the template parameters and arguments
   // only if this is not an explicit instantiation or specialization
@@ -478,9 +476,10 @@ void LinkageComputer::mergeTemplateLV(
   LV.setLinkage(tempLV.getLinkage());
 
   LinkageInfo paramsLV =
-    getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
+      getLVForTemplateParameterList(temp->getTemplateParameters(), 
computation);
   LV.mergeMaybeWithVisibility(paramsLV,
-           considerVisibility && !hasExplicitVisibilityAlready(computation));
+                              considerVisibility &&
+                                  !hasExplicitVisibilityAlready(computation));
 
   // Merge information from the template arguments.  We ignore
   // template-argument visibility if we've got an explicit
@@ -496,8 +495,8 @@ void LinkageComputer::mergeTemplateLV(
 /// arguments and parameters of the given variable template
 /// specialization? As usual, follow class template specialization
 /// logic up to initialization.
-static bool shouldConsiderTemplateVisibility(
-                                 const VarTemplateSpecializationDecl *spec,
+static bool
+shouldConsiderTemplateVisibility(const VarTemplateSpecializationDecl *spec,
                                  LVComputationKind computation) {
   // Include visibility from the template parameters and arguments
   // only if this is not an explicit instantiation or specialization
@@ -529,9 +528,9 @@ void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
   // visibility if we're only considering template arguments.
   VarTemplateDecl *temp = spec->getSpecializedTemplate();
   LinkageInfo tempLV =
-    getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
-  LV.mergeMaybeWithVisibility(tempLV,
-           considerVisibility && !hasExplicitVisibilityAlready(computation));
+      getLVForTemplateParameterList(temp->getTemplateParameters(), 
computation);
+  LV.mergeMaybeWithVisibility(
+      tempLV, considerVisibility && 
!hasExplicitVisibilityAlready(computation));
 
   // Merge information from the template arguments.  We ignore
   // template-argument visibility if we've got an explicit
@@ -554,11 +553,11 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) 
{
     return false;
 
   TemplateSpecializationKind TSK = TSK_Undeclared;
-  if (FunctionTemplateSpecializationInfo *spec
-      = FD->getTemplateSpecializationInfo()) {
+  if (FunctionTemplateSpecializationInfo *spec =
+          FD->getTemplateSpecializationInfo()) {
     TSK = spec->getTemplateSpecializationKind();
   } else if (MemberSpecializationInfo *MSI =
-             FD->getMemberSpecializationInfo()) {
+                 FD->getMemberSpecializationInfo()) {
     TSK = MSI->getTemplateSpecializationKind();
   }
 
@@ -567,8 +566,8 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) {
   // isInlined() only gives meaningful answers on definitions
   // anyway.
   return TSK != TSK_ExplicitInstantiationDeclaration &&
-    TSK != TSK_ExplicitInstantiationDefinition &&
-    FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
+         TSK != TSK_ExplicitInstantiationDefinition && FD->hasBody(Def) &&
+         Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
 }
 
 template <typename T> static bool isFirstInExternCContext(T *D) {
@@ -704,10 +703,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const 
NamedDecl *D,
       // If we're declared in a namespace with a visibility attribute,
       // use that namespace's visibility, and it still counts as explicit.
       for (const DeclContext *DC = D->getDeclContext();
-           !isa<TranslationUnitDecl>(DC);
-           DC = DC->getParent()) {
+           !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) {
         const auto *ND = dyn_cast<NamespaceDecl>(DC);
-        if (!ND) continue;
+        if (!ND)
+          continue;
         if (std::optional<Visibility> Vis =
                 getExplicitVisibility(ND, computation)) {
           LV.mergeVisibility(*Vis, true);
@@ -794,7 +793,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl 
*D,
       mergeTemplateLV(LV, spec, computation);
     }
 
-  //     - a function; or
+    //     - a function; or
   } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
     // In theory, we can modify the function's LV by the LV of its
     // type unless it has C linkage (see comment above about variables
@@ -834,17 +833,17 @@ LinkageComputer::getLVForNamespaceScopeDecl(const 
NamedDecl *D,
     // Consider LV from the template and the template arguments.
     // We're at file scope, so we do not need to worry about nested
     // specializations.
-    if (FunctionTemplateSpecializationInfo *specInfo
-                               = Function->getTemplateSpecializationInfo()) {
+    if (FunctionTemplateSpecializationInfo *specInfo =
+            Function->getTemplateSpecializationInfo()) {
       mergeTemplateLV(LV, Function, specInfo, computation);
     }
 
-  //     - a named class (Clause 9), or an unnamed class defined in a
-  //       typedef declaration in which the class has the typedef name
-  //       for linkage purposes (7.1.3); or
-  //     - a named enumeration (7.2), or an unnamed enumeration
-  //       defined in a typedef declaration in which the enumeration
-  //       has the typedef name for linkage purposes (7.1.3); or
+    //     - a named class (Clause 9), or an unnamed class defined in a
+    //       typedef declaration in which the class has the typedef name
+    //       for linkage purposes (7.1.3); or
+    //     - a named enumeration (7.2), or an unnamed enumeration
+    //       defined in a typedef declaration in which the enumeration
+    //       has the typedef name for linkage purposes (7.1.3); or
   } else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
     // Unnamed tags have no linkage.
     if (!Tag->hasNameForLinkage())
@@ -857,46 +856,46 @@ LinkageComputer::getLVForNamespaceScopeDecl(const 
NamedDecl *D,
       mergeTemplateLV(LV, spec, computation);
     }
 
-  // FIXME: This is not part of the C++ standard any more.
-  //     - an enumerator belonging to an enumeration with external linkage; or
+    // FIXME: This is not part of the C++ standard any more.
+    //     - an enumerator belonging to an enumeration with external linkage; 
or
   } else if (isa<EnumConstantDecl>(D)) {
-    LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
-                                      computation);
+    LinkageInfo EnumLV =
+        getLVForDecl(cast<NamedDecl>(D->getDeclContext()), computation);
     if (!isExternalFormalLinkage(EnumLV.getLinkage()))
       return LinkageInfo::none();
     LV.merge(EnumLV);
 
-  //     - a template
+    //     - a template
   } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
     bool considerVisibility = !hasExplicitVisibilityAlready(computation);
-    LinkageInfo tempLV =
-      getLVForTemplateParameterList(temp->getTemplateParameters(), 
computation);
+    LinkageInfo tempLV = getLVForTemplateParameterList(
+        temp->getTemplateParameters(), computation);
     LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
 
-  //     An unnamed namespace or a namespace declared directly or indirectly
-  //     within an unnamed namespace has internal linkage. All other namespaces
-  //     have external linkage.
-  //
-  // We handled names in anonymous namespaces above.
+    //     An unnamed namespace or a namespace declared directly or indirectly
+    //     within an unnamed namespace has internal linkage. All other
+    //     namespaces have external linkage.
+    //
+    // We handled names in anonymous namespaces above.
   } else if (isa<NamespaceDecl>(D)) {
     return LV;
 
-  // By extension, we assign external linkage to Objective-C
-  // interfaces.
+    // By extension, we assign external linkage to Objective-C
+    // interfaces.
   } else if (isa<ObjCInterfaceDecl>(D)) {
     // fallout
 
   } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
     // A typedef declaration has linkage if it gives a type a name for
     // linkage purposes.
-    if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
+    if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/ true))
       return LinkageInfo::none();
 
   } else if (isa<MSGuidDecl>(D)) {
     // A GUID behaves like an inline variable with external linkage. Fall
     // through.
 
-  // Everything not covered here has no linkage.
+    // Everything not covered here has no linkage.
   } else {
     return LinkageInfo::none();
   }
@@ -909,10 +908,9 @@ LinkageComputer::getLVForNamespaceScopeDecl(const 
NamedDecl *D,
   return LV;
 }
 
-LinkageInfo
-LinkageComputer::getLVForClassMember(const NamedDecl *D,
-                                     LVComputationKind computation,
-                                     bool IgnoreVarTypeLinkage) {
+LinkageInfo LinkageComputer::getLVForClassMember(const NamedDecl *D,
+                                                 LVComputationKind computation,
+                                                 bool IgnoreVarTypeLinkage) {
   // Only certain class members have linkage.  Note that fields don't
   // really have linkage, but it's convenient to say they do for the
   // purposes of calculating linkage of pointer-to-data-member
@@ -923,12 +921,8 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
   // linkage and visibility of a template specialization, we might hit
   // a template template argument that way. If we do, we need to
   // consider its linkage.
-  if (!(isa<CXXMethodDecl>(D) ||
-        isa<VarDecl>(D) ||
-        isa<FieldDecl>(D) ||
-        isa<IndirectFieldDecl>(D) ||
-        isa<TagDecl>(D) ||
-        isa<TemplateDecl>(D)))
+  if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) ||
+        isa<IndirectFieldDecl>(D) || isa<TagDecl>(D) || isa<TemplateDecl>(D)))
     return LinkageInfo::none();
 
   LinkageInfo LV;
@@ -954,14 +948,13 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
     classComputation = withExplicitVisibilityAlready(computation);
 
   LinkageInfo classLV =
-    getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
+      getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
   // The member has the same linkage as the class. If that's not externally
   // visible, we don't need to compute anything about the linkage.
   // FIXME: If we're only computing linkage, can we bail out here?
   if (!isExternallyVisible(classLV.getLinkage()))
     return classLV;
 
-
   // Otherwise, don't merge in classLV yet, because in certain cases
   // we need to completely ignore the visibility from it.
 
@@ -979,8 +972,8 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
 
     // If this is a method template specialization, use the linkage for
     // the template parameters and arguments.
-    if (FunctionTemplateSpecializationInfo *spec
-           = MD->getTemplateSpecializationInfo()) {
+    if (FunctionTemplateSpecializationInfo *spec =
+            MD->getTemplateSpecializationInfo()) {
       mergeTemplateLV(LV, MD, spec, computation);
       if (spec->isExplicitSpecialization()) {
         explicitSpecSuppressor = MD;
@@ -1017,7 +1010,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
       explicitSpecSuppressor = RD;
     }
 
-  // Static data members.
+    // Static data members.
   } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
     if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
       mergeTemplateLV(LV, spec, computation);
@@ -1037,14 +1030,13 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
       explicitSpecSuppressor = VD;
     }
 
-  // Template members.
+    // Template members.
   } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
     bool considerVisibility =
-      (!LV.isVisibilityExplicit() &&
-       !classLV.isVisibilityExplicit() &&
-       !hasExplicitVisibilityAlready(computation));
-    LinkageInfo tempLV =
-      getLVForTemplateParameterList(temp->getTemplateParameters(), 
computation);
+        (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit() &&
+         !hasExplicitVisibilityAlready(computation));
+    LinkageInfo tempLV = getLVForTemplateParameterList(
+        temp->getTemplateParameters(), computation);
     LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
 
     if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
@@ -1168,7 +1160,8 @@ NamedDecl::isReserved(const LangOptions &LangOpts) const {
 
 ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
   StringRef name = getName();
-  if (name.empty()) return SFF_None;
+  if (name.empty())
+    return SFF_None;
 
   if (name.front() == 'C')
     if (name == "CFStringCreateWithFormat" ||
@@ -1289,8 +1282,8 @@ getExplicitVisibilityAux(const NamedDecl *ND,
   if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
     // If the function is a specialization of a template with an
     // explicit visibility attribute, use that.
-    if (FunctionTemplateSpecializationInfo *templateInfo
-          = fn->getTemplateSpecializationInfo())
+    if (FunctionTemplateSpecializationInfo *templateInfo =
+            fn->getTemplateSpecializationInfo())
       return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
                              kind);
 
@@ -1343,7 +1336,7 @@ LinkageInfo LinkageComputer::getLVForClosure(const 
DeclContext *DC,
   auto *VD = dyn_cast<VarDecl>(Owner);
   LinkageInfo OwnerLV =
       VD && VD->getType()->getContainedDeducedType()
-          ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
+          ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/ true)
           : getLVForDecl(Owner, computation);
 
   // A lambda never formally has linkage. But if the owner is externally
@@ -1467,78 +1460,77 @@ LinkageInfo LinkageComputer::computeLVForDecl(const 
NamedDecl *D,
   // Objective-C: treat all Objective-C declarations as having external
   // linkage.
   switch (D->getKind()) {
-    default:
-      break;
+  default:
+    break;
 
-    // Per C++ [basic.link]p2, only the names of objects, references,
-    // functions, types, templates, namespaces, and values ever have linkage.
-    //
-    // Note that the name of a typedef, namespace alias, using declaration,
-    // and so on are not the name of the corresponding type, namespace, or
-    // declaration, so they do *not* have linkage.
-    case Decl::ImplicitParam:
-    case Decl::Label:
-    case Decl::NamespaceAlias:
-    case Decl::ParmVar:
-    case Decl::Using:
-    case Decl::UsingEnum:
-    case Decl::UsingShadow:
-    case Decl::UsingDirective:
-      return LinkageInfo::none();
+  // Per C++ [basic.link]p2, only the names of objects, references,
+  // functions, types, templates, namespaces, and values ever have linkage.
+  //
+  // Note that the name of a typedef, namespace alias, using declaration,
+  // and so on are not the name of the corresponding type, namespace, or
+  // declaration, so they do *not* have linkage.
+  case Decl::ImplicitParam:
+  case Decl::Label:
+  case Decl::NamespaceAlias:
+  case Decl::ParmVar:
+  case Decl::Using:
+  case Decl::UsingEnum:
+  case Decl::UsingShadow:
+  case Decl::UsingDirective:
+    return LinkageInfo::none();
 
-    case Decl::EnumConstant:
-      // C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
-      if (D->getASTContext().getLangOpts().CPlusPlus)
-        return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
-      return LinkageInfo::visible_none();
-
-    case Decl::Typedef:
-    case Decl::TypeAlias:
-      // A typedef declaration has linkage if it gives a type a name for
-      // linkage purposes.
-      if (!cast<TypedefNameDecl>(D)
-               ->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
-        return LinkageInfo::none();
-      break;
+  case Decl::EnumConstant:
+    // C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
+    if (D->getAS...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/210668
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to