@@ -3849,6 +3849,12 @@ class ASTDeclContextNameLookupTrait {
3849
3849
3850
3850
} // namespace
3851
3851
3852
+ bool ASTWriter::isLookupResultExternal (StoredDeclsList &Result,
3853
+ DeclContext *DC) {
3854
+ return Result.hasExternalDecls () &&
3855
+ DC->hasNeedToReconcileExternalVisibleStorage ();
3856
+ }
3857
+
3852
3858
bool ASTWriter::isLookupResultEntirelyExternal (StoredDeclsList &Result,
3853
3859
DeclContext *DC) {
3854
3860
for (auto *D : Result.getLookupResult ())
@@ -3879,17 +3885,20 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
3879
3885
// order.
3880
3886
SmallVector<DeclarationName, 16 > Names;
3881
3887
3882
- // We also track whether we're writing out the DeclarationNameKey for
3883
- // constructors or conversion functions.
3884
- bool IncludeConstructorNames = false ;
3885
- bool IncludeConversionNames = false ;
3888
+ // We also build up small sets of the constructor and conversion function
3889
+ // names which are visible.
3890
+ llvm::SmallPtrSet<DeclarationName, 8 > ConstructorNameSet, ConversionNameSet;
3891
+
3892
+ for (auto &Lookup : *DC->buildLookup ()) {
3893
+ auto &Name = Lookup.first ;
3894
+ auto &Result = Lookup.second ;
3886
3895
3887
- for (auto &[Name, Result] : *DC->buildLookup ()) {
3888
3896
// If there are no local declarations in our lookup result, we
3889
3897
// don't need to write an entry for the name at all. If we can't
3890
3898
// write out a lookup set without performing more deserialization,
3891
3899
// just skip this entry.
3892
- if (isLookupResultEntirelyExternal (Result, DC))
3900
+ if (isLookupResultExternal (Result, DC) &&
3901
+ isLookupResultEntirelyExternal (Result, DC))
3893
3902
continue ;
3894
3903
3895
3904
// We also skip empty results. If any of the results could be external and
@@ -3906,55 +3915,80 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
3906
3915
// results for them. This in almost certainly a bug in Clang's name lookup,
3907
3916
// but that is likely to be hard or impossible to fix and so we tolerate it
3908
3917
// here by omitting lookups with empty results.
3909
- if (Result .getLookupResult ().empty ())
3918
+ if (Lookup. second .getLookupResult ().empty ())
3910
3919
continue ;
3911
3920
3912
- switch (Name .getNameKind ()) {
3921
+ switch (Lookup. first .getNameKind ()) {
3913
3922
default :
3914
- Names.push_back (Name );
3923
+ Names.push_back (Lookup. first );
3915
3924
break ;
3916
3925
3917
3926
case DeclarationName::CXXConstructorName:
3918
- IncludeConstructorNames = true ;
3927
+ assert (isa<CXXRecordDecl>(DC) &&
3928
+ " Cannot have a constructor name outside of a class!" );
3929
+ ConstructorNameSet.insert (Name);
3919
3930
break ;
3920
3931
3921
3932
case DeclarationName::CXXConversionFunctionName:
3922
- IncludeConversionNames = true ;
3933
+ assert (isa<CXXRecordDecl>(DC) &&
3934
+ " Cannot have a conversion function name outside of a class!" );
3935
+ ConversionNameSet.insert (Name);
3923
3936
break ;
3924
3937
}
3925
3938
}
3926
3939
3927
3940
// Sort the names into a stable order.
3928
3941
llvm::sort (Names);
3929
3942
3930
- if (IncludeConstructorNames || IncludeConversionNames ) {
3943
+ if (auto *D = dyn_cast<CXXRecordDecl>(DC) ) {
3931
3944
// We need to establish an ordering of constructor and conversion function
3932
- // names, and they don't have an intrinsic ordering. We also need to write
3933
- // out all constructor and conversion function results if we write out any
3934
- // of them, because they're all tracked under the same lookup key.
3935
- llvm::SmallPtrSet<DeclarationName, 8 > AddedNames;
3936
- for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls ()) {
3937
- if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
3938
- auto Name = ChildND->getDeclName ();
3939
- switch (Name.getNameKind ()) {
3940
- default :
3941
- continue ;
3942
-
3943
- case DeclarationName::CXXConstructorName:
3944
- if (!IncludeConstructorNames)
3945
+ // names, and they don't have an intrinsic ordering.
3946
+
3947
+ // First we try the easy case by forming the current context's constructor
3948
+ // name and adding that name first. This is a very useful optimization to
3949
+ // avoid walking the lexical declarations in many cases, and it also
3950
+ // handles the only case where a constructor name can come from some other
3951
+ // lexical context -- when that name is an implicit constructor merged from
3952
+ // another declaration in the redecl chain. Any non-implicit constructor or
3953
+ // conversion function which doesn't occur in all the lexical contexts
3954
+ // would be an ODR violation.
3955
+ auto ImplicitCtorName = Context->DeclarationNames .getCXXConstructorName (
3956
+ Context->getCanonicalType (Context->getRecordType (D)));
3957
+ if (ConstructorNameSet.erase (ImplicitCtorName))
3958
+ Names.push_back (ImplicitCtorName);
3959
+
3960
+ // If we still have constructors or conversion functions, we walk all the
3961
+ // names in the decl and add the constructors and conversion functions
3962
+ // which are visible in the order they lexically occur within the context.
3963
+ if (!ConstructorNameSet.empty () || !ConversionNameSet.empty ())
3964
+ for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls ())
3965
+ if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
3966
+ auto Name = ChildND->getDeclName ();
3967
+ switch (Name.getNameKind ()) {
3968
+ default :
3945
3969
continue ;
3946
- break ;
3947
3970
3948
- case DeclarationName::CXXConversionFunctionName:
3949
- if (!IncludeConversionNames)
3950
- continue ;
3951
- break ;
3971
+ case DeclarationName::CXXConstructorName:
3972
+ if (ConstructorNameSet.erase (Name))
3973
+ Names.push_back (Name);
3974
+ break ;
3975
+
3976
+ case DeclarationName::CXXConversionFunctionName:
3977
+ if (ConversionNameSet.erase (Name))
3978
+ Names.push_back (Name);
3979
+ break ;
3980
+ }
3981
+
3982
+ if (ConstructorNameSet.empty () && ConversionNameSet.empty ())
3983
+ break ;
3952
3984
}
3953
- // We should include lookup results for this name.
3954
- if (AddedNames.insert (Name).second )
3955
- Names.push_back (Name);
3956
- }
3957
- }
3985
+
3986
+ assert (ConstructorNameSet.empty () && " Failed to find all of the visible "
3987
+ " constructors by walking all the "
3988
+ " lexical members of the context." );
3989
+ assert (ConversionNameSet.empty () && " Failed to find all of the visible "
3990
+ " conversion functions by walking all "
3991
+ " the lexical members of the context." );
3958
3992
}
3959
3993
3960
3994
// Next we need to do a lookup with each name into this decl context to fully
0 commit comments