[clang] [Clang] Only non-overloaded dereference expressions are lvalues (PR #93457)
https://github.com/sdkrystian approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/93457 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)
sdkrystian wrote: @kimgr The linked code seems to only be concerned with the `SourceLocation` of the `Decl` (which should be the same `SourceLocation` returned by `Decl::getLocation`), and the template arguments as written (which can be accessed via `getTemplateArgsAsWritten` per this patch). I would imagine the fix here would be to handle explicit instantiations of class templates the same what you handle explicit instantiations of function templates (which also do not store a `TypeLoc` but can have their template arguments as written accessed in a similar manner). https://github.com/llvm/llvm-project/pull/81642 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement resolution for CWG1835 (PR #92957)
@@ -55,15 +55,21 @@ namespace PR11856 { template T *end(T*); - class X { }; + struct X { }; + struct Y { +int end; + }; template void Foo2() { T it1; -if (it1->end < it1->end) { -} +if (it1->end < it1->end) { } X *x; -if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}} -} +if (x->end < 7) { } // expected-error{{expected '>'}} +// expected-note@-1{{to match this '<'}} +// expected-error@-2{{expected unqualified-id}} sdkrystian wrote: This actually is expected -- see the final note in the comments of the PR. Since we didn't find anything via qualified lookup, we "lock into" the nested-name-specifier interpretation (because it would otherwise be an invalid class member access since such a member doesn't exist). So, we do unqualified lookup, find the template, and try parse `<` as a template argument list. https://github.com/llvm/llvm-project/pull/92957 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Distinguish unresolved templates in UnresolvedLookupExpr (PR #89019)
sdkrystian wrote: @zyn0217 Yes, both examples are of uninstantiable templates & are intended to be diagnosed by #90152. https://github.com/llvm/llvm-project/pull/89019 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement resolution for CWG1835 (PR #92957)
sdkrystian wrote: @Endilll I'm still in the process of writing tests, but I'll add several soon. I'm quite confident about my interpretation being correct but I just want to be 100% sure :). At the very least this patch gets [[basic.lookup.qual.general] example 3](http://eel.is/c++draft/basic.lookup.qual.general#example-3) right, in addition to the examples I provided in the PR. https://github.com/llvm/llvm-project/pull/92957 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement resolution for CWG1835 (PR #92957)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92957 >From 4524db5ae7f3133b51328fbabd1f6188d7d3707b Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 21 May 2024 13:15:24 -0400 Subject: [PATCH 1/2] [WIP][Clang] Implement resolution for CWG1835 --- clang/include/clang/Sema/DeclSpec.h | 8 +++ clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseDeclCXX.cpp | 2 +- clang/lib/Parse/ParseExpr.cpp | 9 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 60 +-- clang/lib/Sema/SemaExprMember.cpp | 10 +--- clang/lib/Sema/SemaPseudoObject.cpp | 16 ++--- clang/lib/Sema/SemaTemplate.cpp | 22 --- clang/lib/Sema/TreeTransform.h| 15 + .../basic.lookup.classref/p1-cxx11.cpp| 16 +++-- .../basic.lookup/basic.lookup.classref/p1.cpp | 16 +++-- .../class.derived/class.member.lookup/p8.cpp | 4 +- clang/test/CXX/drs/cwg1xx.cpp | 9 +-- clang/test/SemaCXX/static-assert-cxx17.cpp| 2 +- .../SemaTemplate/temp_arg_nontype_cxx20.cpp | 2 +- 15 files changed, 128 insertions(+), 65 deletions(-) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..c6d87ca1683a8 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -75,6 +75,7 @@ class CXXScopeSpec { SourceRange Range; NestedNameSpecifierLocBuilder Builder; ArrayRef TemplateParamLists; + NamedDecl *FoundFirstQualifierInScope; public: SourceRange getRange() const { return Range; } @@ -91,6 +92,13 @@ class CXXScopeSpec { return TemplateParamLists; } + void setFoundFirstQualifierInScope(NamedDecl *Found) { +FoundFirstQualifierInScope = Found; + } + NamedDecl *getFirstQualifierFoundInScope() const { +return FoundFirstQualifierInScope; + } + /// Retrieve the representation of the nested-name-specifier. NestedNameSpecifier *getScopeRep() const { return Builder.getRepresentation(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5894239664c15..805d36fd10544 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6891,7 +6891,7 @@ class Sema final : public SemaBase { const TemplateArgumentListInfo *TemplateArgs); ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - tok::TokenKind OpKind, CXXScopeSpec , + bool IsArrow, CXXScopeSpec , SourceLocation TemplateKWLoc, UnqualifiedId , Decl *ObjCImpDecl); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5eaec2b621e6f..b2fa6da002f98 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -720,7 +720,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( return nullptr; } CXXScopeSpec SS; -if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr, +if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, /*ObectHasErrors=*/false, /*EnteringConttext=*/false, /*MayBePseudoDestructor=*/nullptr, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index eb7447fa038e4..b3c25f88b403d 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2254,6 +2254,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } break; } + ParseOptionalCXXScopeSpecifier( SS, ObjectType, LHS.get() && LHS.get()->containsErrors(), /*EnteringContext=*/false, ); @@ -2328,10 +2329,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (!LHS.isInvalid()) -LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, -OpKind, SS, TemplateKWLoc, Name, - CurParsedObjCImpl ? CurParsedObjCImpl->Dcl - : nullptr); +LHS = Actions.ActOnMemberAccessExpr( +getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow, SS, +TemplateKWLoc, Name, +CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); if (!LHS.isInvalid()) { if (Tok.is(tok::less)) checkPotentialAngleBracket(LHS); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index c405fbc0aa421..6efa8925d1446 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -397,11 +397,19 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { while
[clang] [Clang] Implement resolution for CWG1835 (PR #92957)
sdkrystian wrote: (this PR is by no means complete, but I would like feedback regarding the validity of my interpretation of the DR resolution and perhaps some guidance with how to best go about implementing it. The currently included implementation _works_, but I'm uncertain whether it's the best way of going about it). https://github.com/llvm/llvm-project/pull/92957 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement resolution for CWG1835 (PR #92957)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92957 [CWG1835](https://cplusplus.github.io/CWG/issues/1835.html) was one of the many core issues resolved by [P1787R6: Declarations and where to find them](http://wg21.link/p1787r6). Its resolution changes how [member-qualified names](http://eel.is/c++draft/basic.lookup.qual.general#2) are looked up. This patch is a draft implementation of that resolution. Previously, an _identifier_ following `.` or `->` would be first looked up in the type of the object expression (i.e. qualified lookup), and then in the context of the _postfix-expression_ (i.e. unqualified lookup) if nothing was found; the result of the second lookup was required to name a class template. Notably, this second lookup would occur even when the object expression was dependent, and its result would be used to determine whether a `<` token is the start of a _template-argument_list_. The new wording in [[basic.lookup.qual.general] p2](eel.is/c++draft/basic.lookup.qual.general#2) states: > A member-qualified name is the (unique) component name, if any, of > - an _unqualified-id_ or > - a _nested-name-specifier_ of the form _`type-name ::`_ or _`namespace-name > ::`_ > > in the id-expression of a class member access expression. A ***qualified > name*** is > - a member-qualified name or > - the terminal name of > - a _qualified-id_, > - a _using-declarator_, > - a _typename-specifier_, > - a _qualified-namespace-specifier_, or > - a _nested-name-specifier_, _elaborated-type-specifier_, or > _class-or-decltype_ that has a _nested-name-specifier_. > > The _lookup context_ of a member-qualified name is the type of its > associated object expression (considered dependent if the object expression > is type-dependent). The lookup context of any other qualified name is the > type, template, or namespace nominated by the preceding > _nested-name-specifier_. And [[basic.lookup.qual.general] p3](eel.is/c++draft/basic.lookup.qual.general#3) now states: > _Qualified name lookup_ in a class, namespace, or enumeration performs a > search of the scope associated with it except as specified below. Unless > otherwise specified, a qualified name undergoes qualified name lookup in its > lookup context from the point where it appears unless the lookup context > either is dependent and is not the current instantiation or is not a class or > class template. If nothing is found by qualified lookup for a > member-qualified name that is the terminal name of a _nested-name-specifier_ > and is not dependent, it undergoes unqualified lookup. In non-standardese terms, these two paragraphs essentially state the following: - A name that immediately follows `.` or `->` in a class member access expression is a member-qualified name - A member-qualified name will be first looked up in the type of the object expression `T` unless `T` is a dependent type that is _not_ the current instantiation, e.g. ```cpp template struct A { void f(T* t) { this->x; // type of the object expression is 'A'. although 'A' is dependent, it is the // current instantiation so we look up 'x' in the template definition context. t->y; // type of the object expression is 'T' ('->' is transformed to '.' per [expr.ref]). // 'T' is dependent and is *not* the current instantiation, so we lookup 'y' in the // template instantiation context. } }; ``` - If the first lookup finds nothing and: - the member-qualified name is the first component of a _nested-name-specifier_ (which could be an _identifier_ or a _simple-template-id_), and either: - the type of the object expression is the current instantiation and it has no dependent base classes, or - the type of the object expression is not dependent then we lookup the name again, this time via unqualified lookup. Although the second (unqualified) lookup is stated not to occur when the member-qualified name is dependent, a dependent name will _not_ be dependent once the template is instantiated, so the second lookup must "occur" during instantiation if qualified lookup does not find anything. This means that we must perform the second (unqualified) lookup during parsing even when the type of the object expression is dependent, but those results are _not_ used to determine whether a `<` token is the start of a _template-argument_list_; they are stored so we can replicate the second lookup during instantiation. In even simpler terms (paraphrasing the [meeting minutes from the review of P1787](https://wiki.edg.com/bin/view/Wg21summer2020/P1787%28Lookup%29Review2020-06-15Through2020-06-18)): - Unqualified lookup always happens for the first name in a _nested-name-specifier_ that follows `.` or `->` - The result of that lookup is only used to determine whether `<` is the start of a _template-argument-list_ if
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92449 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92449 >From f1a55b4f341990df2dc6edd740801486ca43488a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index de884260790cc..02d9b64c2b14b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10255,15 +10255,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { -CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { +auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 788e93b56bb38..9e890204c78bd 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92597 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Properly set the value category of dependent unary operators (PR #88740)
sdkrystian wrote: Ping @cor3ntin ^ https://github.com/llvm/llvm-project/pull/88740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92597 >From 697004547e8855787e7dd248508c9453b9df7e4d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/8] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; +} + } else if (!BaseType->isDependentType()) { +Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; +return nullptr; + } else { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. @@ -2750,65 +2775,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. -if (!Class->getTypeForDecl()->isDependentType()) +if (!Class->isDependentContext()) Class->setInvalidDecl(); return new (Context) CXXBaseSpecifier( SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, Access, TInfo, EllipsisLoc); } - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { -Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; -return nullptr; - } - - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { -Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; -return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92318 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From 72f0013122b764c7295a9b80b1f886b2eb38fb1d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/5] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6c89d275215de..5894239664c15 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5375,11 +5375,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8991,7 +8989,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f2d0a93d9a1e7..b2077df062d49 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92449 >From 0e73c984a4215207b2842f60ac4dcaeb63230407 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8a7af678b33d3..051814643ed88 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10290,15 +10290,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { -CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { +auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 788e93b56bb38..9e890204c78bd 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From 298b2fec54595e5c3c99070cbe856a36e1b71c95 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/5] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6c89d275215de..5894239664c15 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5375,11 +5375,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8991,7 +8989,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5ecfdee21f09d..ebf02ae566044 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92597 >From 4a535c2f2660583487018f421788cd2b88d8428d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/8] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; +} + } else if (!BaseType->isDependentType()) { +Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; +return nullptr; + } else { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. @@ -2750,65 +2775,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. -if (!Class->getTypeForDecl()->isDependentType()) +if (!Class->isDependentContext()) Class->setInvalidDecl(); return new (Context) CXXBaseSpecifier( SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, Access, TInfo, EllipsisLoc); } - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { -Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; -return nullptr; - } - - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { -Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; -return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92597 >From 4a535c2f2660583487018f421788cd2b88d8428d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/7] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; +} + } else if (!BaseType->isDependentType()) { +Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; +return nullptr; + } else { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. @@ -2750,65 +2775,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. -if (!Class->getTypeForDecl()->isDependentType()) +if (!Class->isDependentContext()) Class->setInvalidDecl(); return new (Context) CXXBaseSpecifier( SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, Access, TInfo, EllipsisLoc); } - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { -Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; -return nullptr; - } - - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { -Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; -return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92452 >From 613560033f7bf9acb9315766291bff07ee9e9b5f Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH 1/3] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5a123b0b86dda..6f5cc58d2f9e1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -742,6 +742,8 @@ Bug Fixes to C++ Support - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). - Fix a bug where the last argument was not considered when considering the most viable function for explicit object argument member functions. Fixes (#GH92188). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 557fe10619c35..05575a837a409 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9217,15 +9217,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { +void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92597 >From 4a535c2f2660583487018f421788cd2b88d8428d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/5] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; +} + } else if (!BaseType->isDependentType()) { +Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; +return nullptr; + } else { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. @@ -2750,65 +2775,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. -if (!Class->getTypeForDecl()->isDependentType()) +if (!Class->isDependentContext()) Class->setInvalidDecl(); return new (Context) CXXBaseSpecifier( SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, Access, TInfo, EllipsisLoc); } - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { -Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; -return nullptr; - } - - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { -Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; -return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if
[clang] [clang-tools-extra] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92597 >From 9d95d211797843f3dc612fe4340354b5fbf6a2fe Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/5] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; +} + } else if (!BaseType->isDependentType()) { +Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; +return nullptr; + } else { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. @@ -2750,65 +2775,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. -if (!Class->getTypeForDecl()->isDependentType()) +if (!Class->isDependentContext()) Class->setInvalidDecl(); return new (Context) CXXBaseSpecifier( SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, Access, TInfo, EllipsisLoc); } - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { -Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; -return nullptr; - } - - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { -Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; -return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From db264c719dfae25a536fb2452328d9aaeeea7b6f Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/4] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d4d4a82525a02..fcc60a2ee4bca 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5374,11 +5374,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8990,7 +8988,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5ecfdee21f09d..ebf02ae566044 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] [Clang][Sema] Fix lookup of dependent operator= named by using-declaration (PR #91503)
sdkrystian wrote: Closing this for now; I'll return to this once we correctly handle dependent `operator=`. https://github.com/llvm/llvm-project/pull/91503 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix lookup of dependent operator= named by using-declaration (PR #91503)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/91503 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92452 >From 187eb245484e21970ac55f05a78d3221f2f07f9a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH 1/3] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2f83f5c6d54e9..3c7e0572e837f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -758,6 +758,8 @@ Bug Fixes to C++ Support - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). - Fix a bug where the last argument was not considered when considering the most viable function for explicit object argument member functions. Fixes (#GH92188). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f2b9202255cd4..4a1d55ea44703 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9217,15 +9217,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { +void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) sdkrystian wrote: I think it would work either way... since this is guarded by `if (FDisConst != NewFDisConst)`, `!NewFDisConst` implies `FDisConst`. https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (PR #92597)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92597 Consider the following: ```cpp template struct A { struct B : A { }; }; ``` According to [[class.derived.general] p2](http://eel.is/c++draft/class.derived.general#2): > [...] A _class-or-decltype_ shall denote a (possibly cv-qualified) class type > that is not an incompletely defined class; any cv-qualifiers are ignored. > [...] Although GCC and EDG rejects this, Clang accepts it. This is incorrect, as `A` is incomplete within its own definition (outside of a complete-class context). This patch correctly diagnoses instances where the current instantiation is used as a base class before it is complete. Conversely, Clang erroneously rejects the following: ```cpp template struct A { struct B; struct C : B { }; struct B : C { }; // error: circular inheritance between 'C' and 'A::B' }; ``` Though it may seem like no valid specialization of this template can be instantiated, an explicit specialization of either member classes for an implicit instantiated specialization of `A` would permit the definition of the other member class to be instantiated, e.g.: ```cpp template<> struct A::B { }; A::C c; // ok ``` So this patch also does away with this error. This means that circular inheritance is diagnosed during instantiation of the definition as a consequence of requiring the base class types to be complete (matching the behavior of GCC and EDG). >From 9d95d211797843f3dc612fe4340354b5fbf6a2fe Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 17 May 2024 13:30:04 -0400 Subject: [PATCH 1/4] [Clang][Sema] Diagnose current instantiation used a incomplete base class --- clang/lib/AST/Type.cpp| 4 + clang/lib/Sema/SemaDeclCXX.cpp| 116 +- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- clang/test/SemaTemplate/dependent-names.cpp | 9 +- .../test/SemaTemplate/destructor-template.cpp | 14 ++- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 6 files changed, 84 insertions(+), 76 deletions(-) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..4ad764b67f81f 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,10 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { +CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); +return Rec->isBeingDefined(); + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8225381985052..84033a602f131 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2704,28 +2704,53 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access = AS_public; QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { -Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; -return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { +// C++ [class.union.general]p4: +// [...] A union shall not be used as a base class. +if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; +} + +// For the MS ABI, propagate DLL attributes to base class templates. +if (Context.getTargetInfo().getCXXABI().isMicrosoft() || +Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { +if (auto *BaseSpec = +dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); +} + } +} - if (BaseType->isDependentType()) { +if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, +SpecifierRange)) { +
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92452 >From 27fab1ec54259941e3ded174de18cd99aa89bf7e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH 1/3] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..411a5f752899d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..22749dc4799bc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { +void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with sdkrystian wrote: Nevermind, I did :) #61004 https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92452 >From 27fab1ec54259941e3ded174de18cd99aa89bf7e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH 1/2] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..411a5f752899d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..22749dc4799bc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { +void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with sdkrystian wrote: I looked, but couldn't find any https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); sdkrystian wrote: Fair enough :) https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() sdkrystian wrote: @AaronBallman Updated https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92452 >From 27fab1ec54259941e3ded174de18cd99aa89bf7e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH 1/2] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..411a5f752899d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..22749dc4799bc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { +void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From 4ae259b21661caae2a9cd89437c56f3915195682 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/4] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 66d5e2d4a4ade..c35cb815fdfeb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5366,11 +5366,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8982,7 +8980,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 274e1fb183534..0e42501ea8ce2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); sdkrystian wrote: I opted for the "return `SourceLocation()` if no `const` qualifier is present" approach because it doesn't require the caller to check `hasMethodTypeQualifiers()` prior to calling `getConstQualifierLoc()`. Makes it less prone to being the cause of future crashes :) https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) sdkrystian wrote: Er, no. We want to suggest removing `const` when `NewFDisConst` is `true`, or suggest inserting it if `false`. https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
@@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with sdkrystian wrote: Don't know, I just happened upon it when working on #92449... I'll check https://github.com/llvm/llvm-project/pull/92452 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92449 >From b56eeb2ef435f06764bac0b062a8a0e747f697d4 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a5350ceb59cb7..420bd2de88686 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10282,15 +10282,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { -CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { +auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..2712f203bbd76 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against
[clang] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (PR #92452)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92452 Clang crashes when diagnosing the following invalid redeclaration in C++11: ```cpp struct A { void f(); }; constexpr void A::f() { } // crash here ``` This happens because `DiagnoseInvalidRedeclaration` tries to create a fix-it to remove `const` from the out-of-line declaration of `f`, but there is no `SourceLocation` for the `const` qualifier (it's implicitly `const` due to `constexpr`) and an assert in `FunctionTypeInfo::getConstQualifierLoc` fails. This patch changes the accessors for _cv-qualifier-seq_ `SourceLocations` in `FunctionTypeInfo` to return an invalid `SourceLocation` if no _cv-qualifier-seq_ is present, and changes `DiagnoseInvalidRedeclaration` to only suggest the removal of the `const` qualifier when it was explicitly specified. >From 27fab1ec54259941e3ded174de18cd99aa89bf7e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 16:42:27 -0400 Subject: [PATCH] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 --- clang/docs/ReleaseNotes.rst| 2 ++ clang/include/clang/Sema/DeclSpec.h| 12 ++-- clang/lib/Sema/SemaDecl.cpp| 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..411a5f752899d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..22749dc4799bc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) +<< NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) +DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) +DB << FixItHint::CreateRemoval(ConstLoc); } else
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92449 >From b56eeb2ef435f06764bac0b062a8a0e747f697d4 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a5350ceb59cb7..420bd2de88686 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10282,15 +10282,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { -CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { +auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..2712f203bbd76 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against
[clang] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (PR #92449)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92449 Clang incorrectly accepts the following when using C++14 or later: ```cpp struct A { template void f() const; template<> constexpr void f(); }; ``` Non-static member functions declared `constexpr` are only implicitly `const` in C++11. This patch makes clang reject the explicit specialization of `f` when using language standards after C++11. >From b56eeb2ef435f06764bac0b062a8a0e747f697d4 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 15:47:04 -0400 Subject: [PATCH] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 --- clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a5350ceb59cb7..420bd2de88686 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10282,15 +10282,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { -CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { +auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..2712f203bbd76 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 0..2a57489083695 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} +
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92425 >From c26365ef78366b5c200d085ddc4211db1b2054e0 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 10:59:03 -0400 Subject: [PATCH 1/3] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ASTContext.cpp | 3 ++- .../temp/temp.decls/temp.fct/temp.func.order/p2.cpp | 11 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321..21f273cf8f54e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b..8fc2bb8c401c2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; -return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, +return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), +AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 0..ca753ec0c2d06 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +template +concept C = sizeof(T) == sizeof(int); + +template +struct A; + +template +struct A; >From 20554c70c5fc3e6f026bc6dcc9f6d8204d2e7a4a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 12:34:39 -0400 Subject: [PATCH 2/3] [FOLD] add issue number to release note --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 21f273cf8f54e..2d2928e418623 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,7 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. -- Fix a bug with checking constrained non-type template parameters for equivalence. +- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). Bug Fixes to AST Handling ^ >From b472d4231a130671e7e32d8318f988c40b064eff Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 13:58:30 -0400 Subject: [PATCH 3/3] [FOLD] address review comments --- .../temp.decls/temp.fct/temp.func.order/p2.cpp | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp index ca753ec0c2d06..df1bbd5fe8128 100644 --- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -1,11 +1,13 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s // expected-no-diagnostics -template -concept C = sizeof(T) == sizeof(int); +namespace GH77377 { + template + concept C = sizeof(T) == sizeof(int); -template -struct A; + template + struct A; -template -struct A; + template + struct A; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92425 >From c26365ef78366b5c200d085ddc4211db1b2054e0 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 10:59:03 -0400 Subject: [PATCH 1/2] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ASTContext.cpp | 3 ++- .../temp/temp.decls/temp.fct/temp.func.order/p2.cpp | 11 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321..21f273cf8f54e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b..8fc2bb8c401c2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; -return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, +return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), +AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 0..ca753ec0c2d06 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +template +concept C = sizeof(T) == sizeof(int); + +template +struct A; + +template +struct A; >From 20554c70c5fc3e6f026bc6dcc9f6d8204d2e7a4a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 12:34:39 -0400 Subject: [PATCH 2/2] [FOLD] add issue number to release note --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 21f273cf8f54e..2d2928e418623 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,7 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. -- Fix a bug with checking constrained non-type template parameters for equivalence. +- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). Bug Fixes to AST Handling ^ ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
@@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. sdkrystian wrote: Good catch :) https://github.com/llvm/llvm-project/pull/92425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92283)
sdkrystian wrote: @Caslyn [[expr.prim.this] p3](http://eel.is/c++draft/expr.prim.this#3) states: > [...] the expression this is a prvalue of type “pointer to _cv-qualifier-seq_ > `X`” wherever `X` is the current class [...] And [[over.match.oper] p1](http://eel.is/c++draft/over.match.oper#1) states: > If no operand of an operator in an expression has a type that is a class or > an enumeration, the operator is assumed to be a built-in operator and > interpreted according to > [[expr.compound]](http://eel.is/c++draft/expr.compound). Since the type of `this` is a pointer, `++this` uses the built-in prefix increment operator. The operand of the built-in prefix increment operator must be an lvalue (and `this` is a prvalue). https://github.com/llvm/llvm-project/pull/92283 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92425 >From c26365ef78366b5c200d085ddc4211db1b2054e0 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 10:59:03 -0400 Subject: [PATCH] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ASTContext.cpp | 3 ++- .../temp/temp.decls/temp.fct/temp.func.order/p2.cpp | 11 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321..21f273cf8f54e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b..8fc2bb8c401c2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; -return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, +return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), +AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 0..ca753ec0c2d06 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +template +concept C = sizeof(T) == sizeof(int); + +template +struct A; + +template +struct A; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/92425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (PR #92425)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92425 When the argument passed to `ASTContext::getUnconstrainedType` is an unconstrained `AutoType`, will return the argument unchanged. However, when called with a constrained `AutoType`, an unconstrained, non-dependent `AutoType` will be returned even if the argument was dependent. Consider the following: ```cpp template concept C = sizeof(T) == sizeof(int); template struct A; template struct A { }; // error: class template partial specialization is not more specialized than the primary template ``` When comparing the template parameters for equivalence, `ASTContext::getUnconstrainedType` is used to remove the constraints per [[temp.over.link] p6 sentence 2](http://eel.is/c++draft/temp.over.link#6.sentence-2). For the template parameter `N` of the class template, it returns a dependent `AutoType`. For the template parameter `N` of the class template partial specialization, it returns a non-dependent `AutoType`. We subsequently compare the adjusted types and find they are not equivalent, thus we consider the partial specialization to not be more specialized than the primary template per [[temp.func.order] p6.2.2](http://eel.is/c++draft/temp.func.order#6.2.2). This patch changes `ASTContext::getUnconstrainedType` such that the dependence of a constrained `AutoType` will propagate to the returned unconstrained `AutoType`. This causes the above example to be correctly accepted, fixing #77377. >From 7905c01b3501f211c044649052d7556b6cacd4a3 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 10:59:03 -0400 Subject: [PATCH] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ASTContext.cpp | 3 ++- .../temp/temp.decls/temp.fct/temp.func.order/p2.cpp | 11 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321..21f273cf8f54e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b..8fc2bb8c401c2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; -return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, +return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), +AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 0..5c908d789d511 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +template +concept C = sizeof(T) == sizeof(int); + +template +struct A; + +template +struct A { }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Properly set the value category of dependent unary operators (PR #88740)
sdkrystian wrote: @cor3ntin I believe this causes the crash reported in #92275 https://github.com/llvm/llvm-project/pull/88740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
sdkrystian wrote: > Yeah, that seems incredibly reasonable and a much lower touch here with fewer > concerns about the side-effects that we got here. Should I open a PR then? https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
sdkrystian wrote: I don't think this is the right approach. I stepped though the example and the reason we reject is because: - We substitute a dependent `AutoType` in for the types of the template parameters when they are initially built. - We call `getMoreSpecialized` determine whether the partial specialization is more specialized than the primary. - We determine that neither template is at least as specialized as the other via `isAtLeastAsSpecializedAs`. - We call `TemplateParameterListsAreEqual` per [[temp.func.order] p6.2.2](http://eel.is/c++draft/temp.func.order#6.2.2) to check for template parameter equivalence, and compare the two template parameters by calling `MatchTemplateParameterKind`. - `MatchTemplateParameterKind` calls `ASTContext::getUnconstrainedType` to get the unconstrained type of the template parameters per [[temp.over.link] p6 sentence 2](http://eel.is/c++draft/temp.over.link#6.sentence-2). For class templates template parameter, it returns the type unchanged (a ***dependent*** `AutoType`). For the class template partial specializations template parameter, it returns an unconstrained `AutoType` ***that isn't dependent***. - We compare the adjusted types and determine they aren't equal, so we consider neither template to be more specialized than the other. So, I think the correct fix is to propagate dependence in `ASTContext::getUnconstrainedType`. I have a branch that implements this [here](https://github.com/sdkrystian/llvm-project/tree/partial-spec-dependent-auto). WDYT @erichkeane @cor3ntin? https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From 6c8646dbb04cc5898fe7f67c9923036b2f68b56d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/3] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..779e3134b3067 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5366,11 +5366,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8982,7 +8980,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec84798e4ce60..ad6cfb632fd94 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92283)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92283 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/91534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318 >From a5ed54f967e4a15a80f41ee648f79e77202906d8 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/2] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..779e3134b3067 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5366,11 +5366,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8982,7 +8980,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo , Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; +// Fake up a nested-name-specifier that starts with the +// injected-class-name of the enclosing class. +QualType T = Context.getTypeDeclType(ContainingClass); +TypeLocBuilder TLB; +TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); +SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); +// Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec84798e4ce60..ad6cfb632fd94 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec , /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec , const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) -return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) -return ExprError(); - +bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, , /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
[clang] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (PR #92318)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92318 According to [[expr.prim.id.general] p2](http://eel.is/c++draft/expr.prim.id.general#2): > If an _id-expression_ `E` denotes a non-static non-type member of some class > `C` at a point where the current class is `X` and > - `E` is potentially evaluated or `C` is `X` or a base class of `X`, and > - `E` is not the _id-expression_ of a class member access expression, and > - if `E` is a _qualified-id_, `E` is not the un-parenthesized operand of the > unary `&` operator, > > the _id-expression_ is transformed into a class member access expression > using `(*this)` as the object expression. Consider the following: ```cpp struct A { void f0(); template void f1(); }; template struct B : T { auto g0() -> decltype(T::f0()); // ok auto g1() -> decltype(T::template f1()); // error: call to non-static member function without an object argument }; template struct B; ``` Clang incorrectly rejects the call to `f1` in the _trailing-return-type_ of `g1`. Furthermore, the following snippet results in a crash during codegen: ```cpp struct A { void f(); }; template struct B : T { template static void g(); template<> void g() { return T::f(); // crash here } }; template struct B; ``` This happens because we unconditionally build a `CXXDependentScopeMemberExpr` (with an implicit object expression) for `T::f` when parsing the template definition, even though we don't know whether `g` is an implicit object member function yet. This patch fixes these issues by instead building `DependentScopeDeclRefExpr`s for such expressions, and only transforming them into implicit class member access expressions during instantiation. Since we implemented the MS "unqualified lookup into dependent bases" extension by building an implicit class member access (and relying on the first component name of the _nested-name-specifier_ to be looked up in the context of the object expression during instantiation), we instead pre-append a fake _nested-name-specifier_ that refers to the injected-class-name of the enclosing class. This patch also refactors `Sema::BuildQualifiedDeclarationNameExpr` and `Sema::BuildQualifiedTemplateIdExpr`, streamlining their implementation and removing any redundant checks. >From a5ed54f967e4a15a80f41ee648f79e77202906d8 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++ clang/lib/Sema/SemaTemplate.cpp | 98 ++- clang/lib/Sema/TreeTransform.h| 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 - ...ms-function-specialization-class-scope.cpp | 52 ++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..779e3134b3067 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5366,11 +5366,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec , const LookupResult , bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec , -const DeclarationNameInfo , -bool IsAddressOfOperand, const Scope *S, -TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec , const DeclarationNameInfo , + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec , LookupResult , bool NeedsADL, @@ -8982,7 +8980,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec , SourceLocation TemplateKWLoc, const DeclarationNameInfo , - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec , SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
[clang] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92283)
sdkrystian wrote: All the new changes are in 5ce0e969f3f94e9694545fe71b14fd8eb086f33e https://github.com/llvm/llvm-project/pull/92283 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91534 >From 34af5511804b8c0fd8b0d742653f6017dd8e9e87 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 8 May 2024 08:43:23 -0400 Subject: [PATCH 1/2] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering --- clang/lib/Sema/SemaTemplateDeduction.cpp | 36 +++--- .../temp.deduct/temp.deduct.partial/p3.cpp| 72 +++ 2 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 853c0e1b50619..b5d405111fe4c 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema , SourceLocation Loc, // is used. if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, -TDF_None, +TDF_AllowCompatibleFunctionType, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; break; @@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , SourceLocation Loc, switch (TPOC) { case TPOC_Call: for (unsigned I = 0, N = Args2.size(); I != N; ++I) - ::MarkUsedTemplateParameters(S.Context, Args2[I], false, - TemplateParams->getDepth(), - UsedParameters); + ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Conversion: -::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false, +::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: -::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, - TemplateParams->getDepth(), - UsedParameters); +// We do not deduce template arguments from the exception specification +// when determining the primary template of a function template +// specialization or when taking the address of a function template. +// Therefore, we do not mark template parameters in the exception +// specification as used during partial ordering to prevent the following +// from being ambiguous: +// +// template +// void f(U) noexcept(noexcept(T())); // #1 +// +// template +// void f(T*) noexcept; // #2 +// +// template<> +// void f(int*) noexcept; // explicit specialization of #2 +// +// Although there is no corresponding wording in the standard, this seems +// to be the intended behavior given the definition of +// 'deduction substitution loci' in [temp.deduct]. +::MarkUsedTemplateParameters( +S.Context, +S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None), +/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; } diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp new file mode 100644 index 0..cc1d4ecda2ecc --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template +struct A { }; + +constexpr A a; +constexpr A b; + +constexpr int* x = nullptr; +constexpr short* y = nullptr; + +namespace ExplicitArgs { + template + constexpr int f(U) noexcept(noexcept(T())) { +return 0; + } + + template + constexpr int f(T*) noexcept { +return 1; + } + + template<> + constexpr int f(int*) noexcept { +return 2; + } + + static_assert(f(1) == 0); + static_assert(f(y) == 1); + static_assert(f(x) == 2); + + template + constexpr int g(U*) noexcept(noexcept(T())) { +return 3; + } + + template + constexpr int g(T) noexcept { +return 4; + } + + template<> + constexpr int g(int*) noexcept { +return 5; + } + + static_assert(g(y) == 3); + static_assert(g(1) == 4); + static_assert(g(x) == 5); +} // namespace ExplicitArgs + +namespace DeducedArgs { + template + constexpr int f(T, A) noexcept(B) { +return 0; + } + + template + constexpr int f(T*, A) noexcept(B && B) { +return 1; + } + + template<> + constexpr int f(int*, A) { +return 2; + } + + static_assert(f(x, a) == 0); + static_assert(f(y, a) == 1); + static_assert(f(x, a) == 2); +} // namespace DeducedArgs >From
[clang] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92283)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92283 This patch reapplies #90500, addressing a bug which caused binary operators with dependent operands to be incorrectly rebuilt by `TreeTransform`. >From 365d97508883eb5a4f9b898f8277d16e1f6d3862 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 13:23:45 -0400 Subject: [PATCH 1/2] Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/Type.h| 5 +- clang/lib/Sema/SemaExpr.cpp | 351 +- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp| 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 clang/test/CXX/over/over.built/ast.cpp| 158 ++-- clang/test/CXX/over/over.built/p10.cpp| 2 +- clang/test/CXX/over/over.built/p11.cpp| 2 +- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp| 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 15 files changed, 402 insertions(+), 245 deletions(-) create mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 49ab222bec405..a2e44efe41347 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,6 +55,9 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). +- Clang now performs semantic analysis for unary operators with dependent operands + that are known to be of non-class non-enumeration type prior to instantiation. + ABI Changes in This Version --- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e6643469e0b33..da3834f19ca04 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,7 +8044,10 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - return isDependentType() || isRecordType() || isEnumeralType(); + if (!CanonicalType->isDependentType()) +return isRecordType() || isEnumeralType(); + return !isArrayType() && !isFunctionType() && !isAnyPointerType() && + !isMemberPointerType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec84798e4ce60..18fd5ba700ad3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus && - (E->getType() == Context.OverloadTy || - // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied - // to pointer types even if the pointee type is dependent. - (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) -return E; + if (getLangOpts().CPlusPlus) { +if (T == Context.OverloadTy || T->isRecordType() || +(T->isDependentType() && !T->isAnyPointerType() && + !T->isMemberPointerType())) + return E; + } // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema , SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + assert(ResType->isAnyPointerType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13957,9 +13957,6 @@ static QualType CheckIncrementDecrementOperand(Sema , Expr *Op, ExprObjectKind , SourceLocation OpLoc, bool IsInc, bool IsPrefix) { - if (Op->isTypeDependent()) -return S.Context.DependentTy; - QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14410,9 +14407,6 @@ static void RecordModifiableNonNullParam(Sema ,
[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , SourceLocation Loc, switch (TPOC) { case TPOC_Call: for (unsigned I = 0, N = Args2.size(); I != N; ++I) - ::MarkUsedTemplateParameters(S.Context, Args2[I], false, - TemplateParams->getDepth(), - UsedParameters); + ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Conversion: -::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false, +::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: -::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, - TemplateParams->getDepth(), - UsedParameters); +// We do not deduce template arguments from the exception specification +// when determining the primary template of a function template +// specialization or when taking the address of a function template. +// Therefore, we do not mark template parameters in the exception +// specification as used during partial ordering to prevent the following +// from being ambiguous: +// +// template +// void f(U) noexcept(noexcept(T())); // #1 +// +// template +// void f(T*) noexcept; // #2 +// +// template<> +// void f(int*) noexcept; // explicit specialization of #2 +// +// Although there is no corresponding wording in the standard, this seems sdkrystian wrote: I've seen it take anywhere from a day to a month. I'll be sure to update this once the issue is opened! https://github.com/llvm/llvm-project/pull/91534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema , SourceLocation Loc, switch (TPOC) { case TPOC_Call: for (unsigned I = 0, N = Args2.size(); I != N; ++I) - ::MarkUsedTemplateParameters(S.Context, Args2[I], false, - TemplateParams->getDepth(), - UsedParameters); + ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Conversion: -::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false, +::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), + /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: -::MarkUsedTemplateParameters(S.Context, FD2->getType(), false, - TemplateParams->getDepth(), - UsedParameters); +// We do not deduce template arguments from the exception specification +// when determining the primary template of a function template +// specialization or when taking the address of a function template. +// Therefore, we do not mark template parameters in the exception +// specification as used during partial ordering to prevent the following +// from being ambiguous: +// +// template +// void f(U) noexcept(noexcept(T())); // #1 +// +// template +// void f(T*) noexcept; // #2 +// +// template<> +// void f(int*) noexcept; // explicit specialization of #2 +// +// Although there is no corresponding wording in the standard, this seems sdkrystian wrote: @erichkeane Filed an issue [here](https://github.com/cplusplus/CWG/issues/537). It might be a little while before an actual core issue is opened, so would it be alright to merge this before that happens? https://github.com/llvm/llvm-project/pull/91534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang] Unify interface for accessing template arguments as written for class/variable template specializations (#81642)" (PR #91393)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/91393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
sdkrystian wrote: The issue seems to be that `TreeTransform::RebuildCXXOperatorCallExpr` relies on `isOverloadableType` to always be true for dependent types https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
sdkrystian wrote: Well this took forever to reduce: ```cpp template struct A; template bool operator==(const A&, const A&); template void f(int *x) { [&](auto *y) { return x == y; }; } void g() { f(nullptr); } ``` We initially build a `CXXOperatorCallExpr` during parsing for the comparison, but `TreeTransform` prematurely rebuilds it as a builtin binary operator when `f` is instantiated. https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
sdkrystian wrote: Reverted in #92149 https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92149)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/92149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92149)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92149 >From 55a5910281b9f6e150adc29b3a1b9c149ca0ef55 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 13:17:29 -0400 Subject: [PATCH] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" This reverts commit 8019cc94658d133583f7be6cd0023d30b0f3. --- clang/docs/ReleaseNotes.rst | 3 - clang/include/clang/AST/Type.h| 5 +- clang/lib/Sema/SemaExpr.cpp | 351 +- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp| 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 clang/test/CXX/over/over.built/ast.cpp| 158 ++-- clang/test/CXX/over/over.built/p10.cpp| 2 +- clang/test/CXX/over/over.built/p11.cpp| 2 +- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp| 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 15 files changed, 245 insertions(+), 402 deletions(-) delete mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a2e44efe41347..49ab222bec405 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,9 +55,6 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). -- Clang now performs semantic analysis for unary operators with dependent operands - that are known to be of non-class non-enumeration type prior to instantiation. - ABI Changes in This Version --- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..e6643469e0b33 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,10 +8044,7 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - if (!CanonicalType->isDependentType()) -return isRecordType() || isEnumeralType(); - return !isArrayType() && !isFunctionType() && !isAnyPointerType() && - !isMemberPointerType(); + return isDependentType() || isRecordType() || isEnumeralType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 18fd5ba700ad3..ec84798e4ce60 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus) { -if (T == Context.OverloadTy || T->isRecordType() || -(T->isDependentType() && !T->isAnyPointerType() && - !T->isMemberPointerType())) - return E; - } + if (getLangOpts().CPlusPlus && + (E->getType() == Context.OverloadTy || + // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied + // to pointer types even if the pointee type is dependent. + (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) +return E; // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema , SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType()); + assert(ResType->isAnyPointerType() && !ResType->isDependentType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13957,6 +13957,9 @@ static QualType CheckIncrementDecrementOperand(Sema , Expr *Op, ExprObjectKind , SourceLocation OpLoc, bool IsInc, bool IsPrefix) { + if (Op->isTypeDependent()) +return S.Context.DependentTy; + QualType ResType = Op->getType(); // Atomic types can be used for increment / decrement where the non-atomic // versions can, so ignore the _Atomic() specifier for the purpose of @@ -14407,6 +14410,9 @@ static void RecordModifiableNonNullParam(Sema , const Expr *Exp) { static QualType CheckIndirectionOperand(Sema , Expr *Op, ExprValueKind
[clang] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" (PR #92149)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/92149 This reverts commit 8019cc94658d133583f7be6cd0023d30b0f3. >From a55eb47a72fd6b5d703e7c20e2cbf5b2aa7fd78d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 14 May 2024 13:17:29 -0400 Subject: [PATCH] Revert "[Clang][Sema] Earlier type checking for builtin unary operators (#90500)" This reverts commit 8019cc94658d133583f7be6cd0023d30b0f3. --- clang/docs/ReleaseNotes.rst | 3 - clang/include/clang/AST/Type.h| 5 +- clang/lib/Sema/SemaExpr.cpp | 354 +- clang/test/AST/ast-dump-expr-json.cpp | 4 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-lambda.cpp| 2 +- .../expr/expr.unary/expr.unary.general/p1.cpp | 65 clang/test/CXX/over/over.built/ast.cpp| 158 ++-- clang/test/CXX/over/over.built/p10.cpp| 2 +- clang/test/CXX/over/over.built/p11.cpp| 2 +- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 25 +- clang/test/Frontend/noderef_templates.cpp | 4 +- clang/test/SemaCXX/cxx2b-deducing-this.cpp| 6 +- .../test/SemaTemplate/class-template-spec.cpp | 12 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 6 +- 15 files changed, 246 insertions(+), 404 deletions(-) delete mode 100644 clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a2e44efe41347..49ab222bec405 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,9 +55,6 @@ C++ Specific Potentially Breaking Changes - Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). -- Clang now performs semantic analysis for unary operators with dependent operands - that are known to be of non-class non-enumeration type prior to instantiation. - ABI Changes in This Version --- - Fixed Microsoft name mangling of implicitly defined variables used for thread diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca04..e6643469e0b33 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -8044,10 +8044,7 @@ inline bool Type::isUndeducedType() const { /// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { - if (!CanonicalType->isDependentType()) -return isRecordType() || isEnumeralType(); - return !isArrayType() && !isFunctionType() && !isAnyPointerType() && - !isMemberPointerType(); + return isDependentType() || isRecordType() || isEnumeralType(); } /// Determines whether this type is written as a typedef-name. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 18fd5ba700ad3..e6c3fa51d54da 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -672,12 +672,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. - if (getLangOpts().CPlusPlus) { -if (T == Context.OverloadTy || T->isRecordType() || -(T->isDependentType() && !T->isAnyPointerType() && - !T->isMemberPointerType())) - return E; - } + if (getLangOpts().CPlusPlus && + (E->getType() == Context.OverloadTy || + // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied + // to pointer types even if the pointee type is dependent. + (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) +return E; // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -10827,7 +10827,7 @@ static bool checkArithmeticIncompletePointerType(Sema , SourceLocation Loc, if (const AtomicType *ResAtomicType = ResType->getAs()) ResType = ResAtomicType->getValueType(); - assert(ResType->isAnyPointerType()); + assert(ResType->isAnyPointerType() && !ResType->isDependentType()); QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteSizedType( Loc, PointeeTy, @@ -13955,8 +13955,11 @@ static QualType CheckCommaOperands(Sema , ExprResult , ExprResult , static QualType CheckIncrementDecrementOperand(Sema , Expr *Op, ExprValueKind , ExprObjectKind , - SourceLocation OpLoc, bool IsInc, - bool IsPrefix) { + SourceLocation OpLoc, + bool IsInc, bool IsPrefix) { + if (Op->isTypeDependent()) +return S.Context.DependentTy; +
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
sdkrystian wrote: This seems to [break something](https://lab.llvm.org/buildbot/#/builders/121/builds/41631) in LLVM... investigating https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Earlier type checking for builtin unary operators (PR #90500)
sdkrystian wrote: @erichkeane Since I addressed @shafik's comments, it this good to be merged? https://github.com/llvm/llvm-project/pull/90500 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Add tests for CWG issues regarding completeness of types (PR #92113)
https://github.com/sdkrystian approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/92113 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: @eaeltsin @ilya-biryukov Fixed in 596a9c1f9b3179b3c77cbde1e96619292ce2a10a https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/91972 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91972 >From a013806c0199e260c37bc6b16b600e61e4caa1c9 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 13 May 2024 10:22:04 -0400 Subject: [PATCH 1/2] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation --- clang/lib/Sema/SemaExprMember.cpp | 10 +- .../CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp| 7 +++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9fa69da4f9685..ac81d4fd57654 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -995,8 +995,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // arrow operator was used with a dependent non-pointer object expression, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || - (IsArrow && !BaseExprType->isPointerType() && - BaseExprType->isDependentType()) || (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && (SS.isSet() ? SS.getScopeRep()->isDependent() : BaseExprType->isDependentType( @@ -1322,7 +1320,11 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , else if (const ObjCObjectPointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); -else if (!BaseType->isDependentType()) { +else if (BaseType->isFunctionType()) + goto fail; +else if (BaseType->isDependentType()) + BaseType = S.Context.DependentTy; +else { if (BaseType->isRecordType()) { // Recover from arrow accesses to records, e.g.: // struct MyRecord foo; @@ -1337,8 +1339,6 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , << FixItHint::CreateReplacement(OpLoc, "."); } IsArrow = false; - } else if (BaseType->isFunctionType()) { -goto fail; } else { S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr.get()->getSourceRange(); diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 1adbc33a701c1..fafd54bde7622 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -551,4 +551,11 @@ namespace N4 { template void D::instantiated(D); // expected-note {{in instantiation of}} + template + struct Typo { +void not_instantiated(Typo a) { + a->Not_instantiated; + a->typo; +} + }; } // namespace N4 >From f13826746be9893a48485275ef819b5cd454a53d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 13 May 2024 11:57:47 -0400 Subject: [PATCH 2/2] [FOLD] fix operator-> with nested-name-specifier --- clang/lib/Sema/SemaExprMember.cpp | 41 ++- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 20 + 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index ac81d4fd57654..244488a0b562b 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1324,26 +1324,24 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , goto fail; else if (BaseType->isDependentType()) BaseType = S.Context.DependentTy; -else { - if (BaseType->isRecordType()) { -// Recover from arrow accesses to records, e.g.: -// struct MyRecord foo; -// foo->bar -// This is actually well-formed in C++ if MyRecord has an -// overloaded operator->, but that should have been dealt with -// by now--or a diagnostic message already issued if a problem -// was encountered while looking for the overloaded operator->. -if (!S.getLangOpts().CPlusPlus) { - S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); -} -IsArrow = false; - } else { -S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) -<< BaseType << BaseExpr.get()->getSourceRange(); -return ExprError(); +else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!S.getLangOpts().CPlusPlus) { +S.Diag(OpLoc,
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
sdkrystian wrote: > I think this needs a release note? I know the only case we have right now is > because of your other patch, but perhaps this affects elsewhere too? @erichkeane I don't think we need a release note since the code changes are in `LookupMemberExpr`, which prior to #90152 had no valid code path for dependent types (and had the assert `assert(!BaseType->isDependentType())` to ensure this). https://github.com/llvm/llvm-project/pull/91972 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/91972 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91972 >From a013806c0199e260c37bc6b16b600e61e4caa1c9 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 13 May 2024 10:22:04 -0400 Subject: [PATCH] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation --- clang/lib/Sema/SemaExprMember.cpp | 10 +- .../CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp| 7 +++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9fa69da4f9685..ac81d4fd57654 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -995,8 +995,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // arrow operator was used with a dependent non-pointer object expression, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || - (IsArrow && !BaseExprType->isPointerType() && - BaseExprType->isDependentType()) || (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && (SS.isSet() ? SS.getScopeRep()->isDependent() : BaseExprType->isDependentType( @@ -1322,7 +1320,11 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , else if (const ObjCObjectPointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); -else if (!BaseType->isDependentType()) { +else if (BaseType->isFunctionType()) + goto fail; +else if (BaseType->isDependentType()) + BaseType = S.Context.DependentTy; +else { if (BaseType->isRecordType()) { // Recover from arrow accesses to records, e.g.: // struct MyRecord foo; @@ -1337,8 +1339,6 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , << FixItHint::CreateReplacement(OpLoc, "."); } IsArrow = false; - } else if (BaseType->isFunctionType()) { -goto fail; } else { S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr.get()->getSourceRange(); diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 1adbc33a701c1..fafd54bde7622 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -551,4 +551,11 @@ namespace N4 { template void D::instantiated(D); // expected-note {{in instantiation of}} + template + struct Typo { +void not_instantiated(Typo a) { + a->Not_instantiated; + a->typo; +} + }; } // namespace N4 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: @ilya-biryukov See #91972 https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (PR #91972)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/91972 Fixes [this bug](https://github.com/llvm/llvm-project/pull/90152#issuecomment-2107363977) introduced in #90152. This bug occurs when typo-correction attempts to fix a reference to a non-existent member of the current instantiation (even though `operator->` may return a different type than the object type). This patch fixes it by simply considering the object expression to be `ASTContext::DependentTy` when the arrow operator is used with a dependent non-pointer non-function operand (after any implicit conversions). >From f5d456a9f042dd0076d0c6e8244a59c693f41132 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 13 May 2024 10:22:04 -0400 Subject: [PATCH] [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation --- clang/lib/Sema/SemaExprMember.cpp | 14 +++--- .../temp/temp.res/temp.dep/temp.dep.type/p4.cpp| 7 +++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9fa69da4f9685..a3411b3036d5e 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -995,11 +995,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // arrow operator was used with a dependent non-pointer object expression, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || - (IsArrow && !BaseExprType->isPointerType() && - BaseExprType->isDependentType()) || (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && - (SS.isSet() ? SS.getScopeRep()->isDependent() - : BaseExprType->isDependentType( + (SS.isSet() ? SS.getScopeRep()->isDependent() + : BaseExprType->isDependentType( return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, R.getLookupNameInfo(), TemplateArgs); @@ -1322,7 +1320,11 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , else if (const ObjCObjectPointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); -else if (!BaseType->isDependentType()) { +else if (BaseType->isFunctionType()) + goto fail; +else if (BaseType->isDependentType()) + BaseType = S.Context.DependentTy; +else { if (BaseType->isRecordType()) { // Recover from arrow accesses to records, e.g.: // struct MyRecord foo; @@ -1337,8 +1339,6 @@ static ExprResult LookupMemberExpr(Sema , LookupResult , << FixItHint::CreateReplacement(OpLoc, "."); } IsArrow = false; - } else if (BaseType->isFunctionType()) { -goto fail; } else { S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr.get()->getSourceRange(); diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 1adbc33a701c1..fafd54bde7622 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -551,4 +551,11 @@ namespace N4 { template void D::instantiated(D); // expected-note {{in instantiation of}} + template + struct Typo { +void not_instantiated(Typo a) { + a->Not_instantiated; + a->typo; +} + }; } // namespace N4 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: @ilya-biryukov I can fix this quickly (less than an hour). https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: Repro: ```cpp template struct Typo { Typo(const Typo& t) { t->typo; // error t->Typp; // error t->Tzpo; // error t->ty; // ok } }; ``` https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: @ilya-biryukov Actually, that is an incredibly useful piece of information :) I think this is an issue with type correction... https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang] Unify interface for accessing template arguments as written for class/variable template specializations (#81642)" (PR #91393)
sdkrystian wrote: @adrian-prantl I tested this patch locally and it fixes the crash in LLDB https://github.com/llvm/llvm-project/pull/91393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent
sdkrystian wrote: @dyung Per [[temp.dep.type] p10.11](http://eel.is/c++draft/temp.dep.type#10.11): > A type is dependent if it is > - [...] > - denoted by a _simple-template-id_ in which either the template name is a > template parameter or any of the template arguments is a dependent type or an > expression that is type-dependent or value-dependent or is a pack expansion, > - [...] In this case, `self` is a typedef for `COneSet` (the injected-class-name of the class template). When used as a _type-name_, the injected-class-name of a class template is equivalent to a _simple-template-id_ with the template arguments of the template parameters of that template. Despite that type _being_ the current instantiation, it is still considered to be a dependent type (name lookup has special rules when the lookup context is dependent _and_ is the current instantiation). Since `pSetOther` names a declaration that has a dependent type, `SWAP(pSetOther)` is a dependent call. https://github.com/llvm/llvm-project/pull/90152 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revert changes to operator= lookup in templated classes from #91498, #90999, and #90152 (PR #91620)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/91620 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revert changes to operator= lookup in templated classes from #91498, #90999, and #90152 (PR #91620)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91620 >From 7b2f3da17dfc93a4f0aa69ad4da90707b6f2e8b6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 9 May 2024 12:30:28 -0400 Subject: [PATCH 1/3] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" This reverts commit 62b5b61f436add042d8729dc9837d055613180d9. --- clang/lib/Sema/SemaLookup.cpp | 35 --- clang/lib/Sema/SemaTemplate.cpp | 7 ++-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 13 --- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e20de338ebb16..e63da5875d2c9 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1267,20 +1267,6 @@ struct FindLocalExternScope { LookupResult bool OldFindLocalExtern; }; - -/// Returns true if 'operator=' should be treated as a dependent name. -bool isDependentAssignmentOperator(DeclarationName Name, - DeclContext *LookupContext) { - const auto *LookupRecord = dyn_cast_if_present(LookupContext); - // If the lookup context is the current instantiation but we are outside a - // complete-class context, we will never find the implicitly declared - // copy/move assignment operators because they are declared at the closing '}' - // of the class specifier. In such cases, we treat 'operator=' like any other - // unqualified name because the results of name lookup in the template - // definition/instantiation context will always be the same. - return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && - !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); -} } // end anonymous namespace bool Sema::CppLookupName(LookupResult , Scope *S) { @@ -1289,6 +1275,13 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { DeclarationName Name = R.getLookupName(); Sema::LookupNameKind NameKind = R.getLookupKind(); + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { +for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = PreS->getEntity()) +DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); + } // C++23 [temp.dep.general]p2: // The component name of an unqualified-id is dependent if // - it is a conversion-function-id whose conversion-type-id @@ -1306,8 +1299,9 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) if (DeclContext *DC = PreS->getEntity()) { -if (!R.isTemplateNameLookup() && -isDependentAssignmentOperator(Name, DC)) { +if (DC->isDependentContext() && isa(DC) && +Name.getCXXOverloadedOperator() == OO_Equal && +!R.isTemplateNameLookup()) { R.setNotFoundInCurrentInstantiation(); return false; } @@ -2478,6 +2472,8 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, } } QL(LookupCtx); + bool TemplateNameLookup = R.isTemplateNameLookup(); + CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (!InUnqualifiedLookup && !R.isForRedeclaration()) { // C++23 [temp.dep.type]p5: // A qualified name is dependent if @@ -2490,14 +2486,13 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, if (DeclarationName Name = R.getLookupName(); (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && Name.getCXXNameType()->isDependentType()) || -(!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, LookupCtx))) { +(Name.getCXXOverloadedOperator() == OO_Equal && LookupRec && + LookupRec->isDependentContext() && !TemplateNameLookup)) { R.setNotFoundInCurrentInstantiation(); return false; } } - CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (LookupRec) @@ -2609,7 +2604,7 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, // template, and if the name is used as a template-name, the // reference refers to the class template itself and not a // specialization thereof, and is not ambiguous. -if (R.isTemplateNameLookup()) +if (TemplateNameLookup) if (auto *TD = getAsTemplateNameDecl(ND)) ND = TD; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480bc74c2001a..7e57fa0696725 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,7 +726,7 @@
[clang] [Clang][Sema] Revert changes to operator= lookup in templated classes from #91498, #90999, and #90152 (PR #91620)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/91620 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revert changes to operator= lookup in templated classes from #91498, #90999, and #90152 (PR #91620)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/91620 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" (PR #91620)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91620 >From 7b2f3da17dfc93a4f0aa69ad4da90707b6f2e8b6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 9 May 2024 12:30:28 -0400 Subject: [PATCH 1/3] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" This reverts commit 62b5b61f436add042d8729dc9837d055613180d9. --- clang/lib/Sema/SemaLookup.cpp | 35 --- clang/lib/Sema/SemaTemplate.cpp | 7 ++-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 13 --- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e20de338ebb16..e63da5875d2c9 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1267,20 +1267,6 @@ struct FindLocalExternScope { LookupResult bool OldFindLocalExtern; }; - -/// Returns true if 'operator=' should be treated as a dependent name. -bool isDependentAssignmentOperator(DeclarationName Name, - DeclContext *LookupContext) { - const auto *LookupRecord = dyn_cast_if_present(LookupContext); - // If the lookup context is the current instantiation but we are outside a - // complete-class context, we will never find the implicitly declared - // copy/move assignment operators because they are declared at the closing '}' - // of the class specifier. In such cases, we treat 'operator=' like any other - // unqualified name because the results of name lookup in the template - // definition/instantiation context will always be the same. - return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && - !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); -} } // end anonymous namespace bool Sema::CppLookupName(LookupResult , Scope *S) { @@ -1289,6 +1275,13 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { DeclarationName Name = R.getLookupName(); Sema::LookupNameKind NameKind = R.getLookupKind(); + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { +for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = PreS->getEntity()) +DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); + } // C++23 [temp.dep.general]p2: // The component name of an unqualified-id is dependent if // - it is a conversion-function-id whose conversion-type-id @@ -1306,8 +1299,9 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) if (DeclContext *DC = PreS->getEntity()) { -if (!R.isTemplateNameLookup() && -isDependentAssignmentOperator(Name, DC)) { +if (DC->isDependentContext() && isa(DC) && +Name.getCXXOverloadedOperator() == OO_Equal && +!R.isTemplateNameLookup()) { R.setNotFoundInCurrentInstantiation(); return false; } @@ -2478,6 +2472,8 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, } } QL(LookupCtx); + bool TemplateNameLookup = R.isTemplateNameLookup(); + CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (!InUnqualifiedLookup && !R.isForRedeclaration()) { // C++23 [temp.dep.type]p5: // A qualified name is dependent if @@ -2490,14 +2486,13 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, if (DeclarationName Name = R.getLookupName(); (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && Name.getCXXNameType()->isDependentType()) || -(!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, LookupCtx))) { +(Name.getCXXOverloadedOperator() == OO_Equal && LookupRec && + LookupRec->isDependentContext() && !TemplateNameLookup)) { R.setNotFoundInCurrentInstantiation(); return false; } } - CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (LookupRec) @@ -2609,7 +2604,7 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, // template, and if the name is used as a template-name, the // reference refers to the class template itself and not a // specialization thereof, and is not ambiguous. -if (R.isTemplateNameLookup()) +if (TemplateNameLookup) if (auto *TD = getAsTemplateNameDecl(ND)) ND = TD; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480bc74c2001a..7e57fa0696725 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,7 +726,7 @@
[clang] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" (PR #91620)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91620 >From 7b2f3da17dfc93a4f0aa69ad4da90707b6f2e8b6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 9 May 2024 12:30:28 -0400 Subject: [PATCH 1/4] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" This reverts commit 62b5b61f436add042d8729dc9837d055613180d9. --- clang/lib/Sema/SemaLookup.cpp | 35 --- clang/lib/Sema/SemaTemplate.cpp | 7 ++-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 13 --- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e20de338ebb16..e63da5875d2c9 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1267,20 +1267,6 @@ struct FindLocalExternScope { LookupResult bool OldFindLocalExtern; }; - -/// Returns true if 'operator=' should be treated as a dependent name. -bool isDependentAssignmentOperator(DeclarationName Name, - DeclContext *LookupContext) { - const auto *LookupRecord = dyn_cast_if_present(LookupContext); - // If the lookup context is the current instantiation but we are outside a - // complete-class context, we will never find the implicitly declared - // copy/move assignment operators because they are declared at the closing '}' - // of the class specifier. In such cases, we treat 'operator=' like any other - // unqualified name because the results of name lookup in the template - // definition/instantiation context will always be the same. - return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && - !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); -} } // end anonymous namespace bool Sema::CppLookupName(LookupResult , Scope *S) { @@ -1289,6 +1275,13 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { DeclarationName Name = R.getLookupName(); Sema::LookupNameKind NameKind = R.getLookupKind(); + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { +for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = PreS->getEntity()) +DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); + } // C++23 [temp.dep.general]p2: // The component name of an unqualified-id is dependent if // - it is a conversion-function-id whose conversion-type-id @@ -1306,8 +1299,9 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) if (DeclContext *DC = PreS->getEntity()) { -if (!R.isTemplateNameLookup() && -isDependentAssignmentOperator(Name, DC)) { +if (DC->isDependentContext() && isa(DC) && +Name.getCXXOverloadedOperator() == OO_Equal && +!R.isTemplateNameLookup()) { R.setNotFoundInCurrentInstantiation(); return false; } @@ -2478,6 +2472,8 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, } } QL(LookupCtx); + bool TemplateNameLookup = R.isTemplateNameLookup(); + CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (!InUnqualifiedLookup && !R.isForRedeclaration()) { // C++23 [temp.dep.type]p5: // A qualified name is dependent if @@ -2490,14 +2486,13 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, if (DeclarationName Name = R.getLookupName(); (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && Name.getCXXNameType()->isDependentType()) || -(!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, LookupCtx))) { +(Name.getCXXOverloadedOperator() == OO_Equal && LookupRec && + LookupRec->isDependentContext() && !TemplateNameLookup)) { R.setNotFoundInCurrentInstantiation(); return false; } } - CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (LookupRec) @@ -2609,7 +2604,7 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, // template, and if the name is used as a template-name, the // reference refers to the class template itself and not a // specialization thereof, and is not ambiguous. -if (R.isTemplateNameLookup()) +if (TemplateNameLookup) if (auto *TD = getAsTemplateNameDecl(ND)) ND = TD; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480bc74c2001a..7e57fa0696725 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,7 +726,7 @@
[clang] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" (PR #91620)
sdkrystian wrote: Is it alright to partially revert commits in a single PR? If so, I'm just going to revert all the `operator=` related changes from #91498, #90999, and #90152. https://github.com/llvm/llvm-project/pull/91620 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" (PR #91620)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/91620 This reverts commit 62b5b61f436add042d8729dc9837d055613180d9 (#91498). >From 7b2f3da17dfc93a4f0aa69ad4da90707b6f2e8b6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 9 May 2024 12:30:28 -0400 Subject: [PATCH] Revert "[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (#91498)" This reverts commit 62b5b61f436add042d8729dc9837d055613180d9. --- clang/lib/Sema/SemaLookup.cpp | 35 --- clang/lib/Sema/SemaTemplate.cpp | 7 ++-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 13 --- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e20de338ebb1..e63da5875d2c 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1267,20 +1267,6 @@ struct FindLocalExternScope { LookupResult bool OldFindLocalExtern; }; - -/// Returns true if 'operator=' should be treated as a dependent name. -bool isDependentAssignmentOperator(DeclarationName Name, - DeclContext *LookupContext) { - const auto *LookupRecord = dyn_cast_if_present(LookupContext); - // If the lookup context is the current instantiation but we are outside a - // complete-class context, we will never find the implicitly declared - // copy/move assignment operators because they are declared at the closing '}' - // of the class specifier. In such cases, we treat 'operator=' like any other - // unqualified name because the results of name lookup in the template - // definition/instantiation context will always be the same. - return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && - !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); -} } // end anonymous namespace bool Sema::CppLookupName(LookupResult , Scope *S) { @@ -1289,6 +1275,13 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { DeclarationName Name = R.getLookupName(); Sema::LookupNameKind NameKind = R.getLookupKind(); + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { +for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = PreS->getEntity()) +DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); + } // C++23 [temp.dep.general]p2: // The component name of an unqualified-id is dependent if // - it is a conversion-function-id whose conversion-type-id @@ -1306,8 +1299,9 @@ bool Sema::CppLookupName(LookupResult , Scope *S) { if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) if (DeclContext *DC = PreS->getEntity()) { -if (!R.isTemplateNameLookup() && -isDependentAssignmentOperator(Name, DC)) { +if (DC->isDependentContext() && isa(DC) && +Name.getCXXOverloadedOperator() == OO_Equal && +!R.isTemplateNameLookup()) { R.setNotFoundInCurrentInstantiation(); return false; } @@ -2478,6 +2472,8 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, } } QL(LookupCtx); + bool TemplateNameLookup = R.isTemplateNameLookup(); + CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (!InUnqualifiedLookup && !R.isForRedeclaration()) { // C++23 [temp.dep.type]p5: // A qualified name is dependent if @@ -2490,14 +2486,13 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, if (DeclarationName Name = R.getLookupName(); (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && Name.getCXXNameType()->isDependentType()) || -(!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, LookupCtx))) { +(Name.getCXXOverloadedOperator() == OO_Equal && LookupRec && + LookupRec->isDependentContext() && !TemplateNameLookup)) { R.setNotFoundInCurrentInstantiation(); return false; } } - CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (LookupRec) @@ -2609,7 +2604,7 @@ bool Sema::LookupQualifiedName(LookupResult , DeclContext *LookupCtx, // template, and if the name is used as a template-name, the // reference refers to the class template itself and not a // specialization thereof, and is not ambiguous. -if (R.isTemplateNameLookup()) +if (TemplateNameLookup) if (auto *TD = getAsTemplateNameDecl(ND)) ND = TD; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480bc74c2001..7e57fa069672 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++
[clang] [Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (PR #91498)
sdkrystian wrote: @aeubanks I think I'm going to revert this & maybe partially revert the changes in #90152 which cause `operator=` to be treated as a dependent name when the current class is templated. There are lots of edge cases that need to be accounted for. Thoughts @erichkeane ? https://github.com/llvm/llvm-project/pull/91498 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (PR #91498)
sdkrystian wrote: @glandium I've reduced it to the following: ```cpp template struct A { static constexpr bool B = true; }; template struct C { }; template struct D { C::B> f(); }; template auto D::f() -> C::B> { } ``` The problem is that we build a `DependentScopeDeclRefExpr` for `A::B` in the first declaration of `f`, and a `CXXDependentScopeMemberExpr` for the second declaration of `f`. Since we have no idea whether `A::B` will be an implicit member access, I think that the correct behavior is that `ActOnDependentIdExpression` should _never_ build a `CXXDependentScopeMemberExpr`. https://github.com/llvm/llvm-project/pull/91498 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (PR #91534)
sdkrystian wrote: @erichkeane Release note added https://github.com/llvm/llvm-project/pull/91534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits