https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/237773
Taking advantage of C++ standard rules, we can take a shortcut to determine if a static data member is out-of-line. Use this to speed up VarDecl::isThisDeclarationADefinition. Expected ctt improvement around 0.4%. >From f2f3dddfe0985cbf05c2683344c4fd52dae01093 Mon Sep 17 00:00:00 2001 From: Eli Friedman <[email protected]> Date: Sun, 1 Nov 2026 12:52:54 -0800 Subject: [PATCH] [clang] Implement fast isOutOfLine() for static data members. Taking advantage of C++ standard rules, we can take a shortcut to determine if a static data member is out-of-line. Use this to speed up VarDecl::isThisDeclarationADefinition. Expected ctt improvement around 0.4%. --- clang/lib/AST/Decl.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index bbc1e37602ec7..c6c2043614aa9 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2237,6 +2237,21 @@ bool VarDecl::isInExternCXXContext() const { VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); } +static bool isStaticDataMemberOutOfLine(const VarDecl *VD) { + // A static data member is out-of-line if and only if it is not declared in + // the definition of a class. ([class.mem.general] says all declarations + // in a class are members outside of a specific list of exceptions.) + // + // For invalid decls, this shortcut can produce different results from a full + // check of the lexical and semantic contexts, but nothing should care about + // that. + // + // It might be possible to implement a similar shortcut for other member + // declarations, but it would need to account for friend declarations. + assert(VD->isStaticDataMember()); + return !isa<CXXRecordDecl>(VD->getLexicalDeclContext()); +} + VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(ASTContext &C) const { if (isThisDeclarationADemotedDefinition()) @@ -2256,15 +2271,15 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // FIXME: How do you declare (but not define) a partial specialization of // a static data member template outside the containing class? if (isStaticDataMember()) { - bool IsOutOfLine = isOutOfLine(); + bool IsOutOfLine = isStaticDataMemberOutOfLine(this); if (IsOutOfLine && !(getCanonicalDecl()->isInline() && getCanonicalDecl()->isConstexpr() && - !getCanonicalDecl()->isOutOfLine()) && + !isStaticDataMemberOutOfLine(getCanonicalDecl())) && (hasInit() || // If the first declaration is out-of-line, this may be an // instantiation of an out-of-line partial specialization of a variable // template for which we have not yet instantiated the initializer. - (getFirstDecl()->isOutOfLine() + (isStaticDataMemberOutOfLine(getFirstDecl()) ? getTemplateSpecializationKind() == TSK_Undeclared : getTemplateSpecializationKind() != TSK_ExplicitSpecialization) || @@ -2446,19 +2461,10 @@ bool VarDecl::hasInitWithSideEffects() const { } bool VarDecl::isOutOfLine() const { - if (Decl::isOutOfLine()) - return true; - - if (!isStaticDataMember()) - return false; - - // If this static data member was instantiated from a static data member of - // a class template, check whether that static data member was defined - // out-of-line. - if (VarDecl *VD = getInstantiatedFromStaticDataMember()) - return VD->isOutOfLine(); + if (isStaticDataMember()) + return isStaticDataMemberOutOfLine(this); - return false; + return Decl::isOutOfLine(); } void VarDecl::setInit(Expr *I) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
