- Fix crash when evaluating consteval constructor of derived class whose base
has more than one field.
(`#60166 <https://github.com/llvm/llvm-project/issues/60166>`_)
-- Fix an issue about ``decltype`` in the members of class templates derived from
- templates with related parameters.
- (`#58674 <https://github.com/llvm/llvm-project/issues/58674>`_)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
///
/// \param Base the base class we are searching for.
///
- /// \param LookupInDependentTypes whether to look up in dependent types.
- ///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(const CXXRecordDecl *Base,
- bool LookupInDependentTypes = false) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base) const;
/// Determine whether this class is derived from the type \p Base.
///
/// \param Paths will contain the paths taken from the current class to the
/// given \p Base class.
///
- /// \param LookupInDependentTypes whether to look up independent types.
- ///
/// \returns true if this class is derived from \p Base, false otherwise.
///
/// \todo add a separate parameter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
- bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths,
- bool LookupInDependentTypes = false) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// Determine whether this class is virtually derived from
/// the class \p Base.
std::swap(DetectedVirtual, Other.DetectedVirtual);
}
-bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
- bool LookupInDependentTypes) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
- return isDerivedFrom(Base, Paths, LookupInDependentTypes);
+ return isDerivedFrom(Base, Paths);
}
bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
- CXXBasePaths &Paths,
- bool LookupInDependentTypes) const {
+ CXXBasePaths &Paths) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
return Specifier->getType()->getAsRecordDecl() &&
FindBaseClass(Specifier, Path, BaseDecl);
},
- Paths, LookupInDependentTypes);
+ Paths);
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
} else if (VisitBase) {
CXXRecordDecl *BaseRecord;
if (LookupInDependent) {
- BaseRecord = cast_if_present<CXXRecordDecl>(
- BaseSpec.getType()->getAsRecordDecl());
- if (!BaseRecord) {
- if (const TemplateSpecializationType *TST =
- BaseSpec.getType()->getAs<TemplateSpecializationType>()) {
- TemplateName TN = TST->getTemplateName();
- if (auto *TD =
- dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
- BaseRecord = TD->getTemplatedDecl();
- }
+ BaseRecord = nullptr;
+ const TemplateSpecializationType *TST =
+ BaseSpec.getType()->getAs<TemplateSpecializationType>();
+ if (!TST) {
+ if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
+ BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
+ } else {
+ TemplateName TN = TST->getTemplateName();
+ if (auto *TD =
+ dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
+ BaseRecord = TD->getTemplatedDecl();
}
if (BaseRecord) {
if (!BaseRecord->hasDefinition() ||
// to get this right here so that we don't end up making a
// spuriously dependent expression if we're inside a dependent
// instance method.
- //
- // We also don't need to do this if R resolved to a member in another
- // class, which can happen in an unevaluated operand:
- //
- // C++ [expr.prim.id]p3.3:
- // If that id-expression denotes a non-static data member and it
- // appears in an unevaluated operand.
if (!R.empty() && (*R.begin())->isCXXClassMember()) {
- bool MightBeImplicitMember = true, CheckField = true;
- if (IsAddressOfOperand) {
- MightBeImplicitMember = SS.isEmpty() && !R.isOverloadedResult();
- CheckField = !R.isUnresolvableResult();
- }
- if (MightBeImplicitMember && CheckField) {
- if (R.isSingleResult() &&
- isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl())) {
- auto Class = cast<CXXRecordDecl>((*R.begin())->getDeclContext());
- for (auto Curr = S->getLookupEntity(); Curr && !Curr->isFileContext();
- Curr = Curr->getParent()) {
- if (auto ThisClass = dyn_cast_if_present<CXXRecordDecl>(Curr)) {
- if ((MightBeImplicitMember =
- ThisClass->Equals(Class) ||
- ThisClass->isDerivedFrom(Class,
- /*LookupIndependent=*/true)))
- break;
- }
- }
- } else if (IsAddressOfOperand)
- MightBeImplicitMember = false;
- }
+ bool MightBeImplicitMember;
+ if (!IsAddressOfOperand)
+ MightBeImplicitMember = true;
+ else if (!SS.isEmpty())
+ MightBeImplicitMember = false;
+ else if (R.isOverloadedResult())
+ MightBeImplicitMember = false;
+ else if (R.isUnresolvableResult())
+ MightBeImplicitMember = true;
+ else
+ MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
+ isa<IndirectFieldDecl>(R.getFoundDecl()) ||
+ isa<MSPropertyDecl>(R.getFoundDecl());
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
+++ /dev/null
-// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s
-
-// CHECK: [[FOO:%.+]] = type { i32 }
-struct foo {
- int val;
-};
-
-template <typename T> struct bar : T {
-};
-
-struct baz : bar<foo> {
- // CHECK-LABEL: define{{.*}} i32 @_ZN3baz3getEv
- // CHECK: {{%.+}} = getelementptr inbounds [[FOO]], ptr {{%.+}}, i32 0, i32 0
- int get() {
- return val;
- }
-};
-
-int qux() {
- auto f = baz{};
- return f.get();
-}
template<class T> void foo(decltype(T(LP1{ .p1 = g1, .p1.x[1] = 'x' }))) {}
}
-namespace GH58674 {
- struct Foo {
- float value_;
- struct nested {
- float value_;
- };
- };
-
- template <typename T>
- struct TemplateFoo {
- float value_;
- };
-
- float bar;
-
- template <typename T>
- struct Animal{};
-
- template <typename T>
- class Cat : Animal<T> {
- using okay = decltype(Foo::value_);
- using also_okay = decltype(bar);
- using okay2 = decltype(Foo::nested::value_);
- using okay3 = decltype(TemplateFoo<T>::value_);
- public:
- void meow() {
- using okay = decltype(Foo::value_);
- using also_okay = decltype(bar);
- using okay2 = decltype(Foo::nested::value_);
- using okay3 = decltype(TemplateFoo<T>::value_);
- }
- };
-
- void baz() {
- Cat<void>{}.meow();
- }
-}
-
template<typename>
class conditional {
};