@@ -783,51 +783,77 @@ static void ProcessVersionedAPINotes(
783783 }
784784}
785785
786+ static std::optional<api_notes::Context>
787+ UnwindNamespaceContext (DeclContext *DC, api_notes::APINotesManager &APINotes) {
788+ if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
789+ for (auto Reader : APINotes.findAPINotes (NamespaceContext->getLocation ())) {
790+ // Retrieve the context ID for the parent namespace of the decl.
791+ std::stack<NamespaceDecl *> NamespaceStack;
792+ {
793+ for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
794+ CurrentNamespace =
795+ dyn_cast<NamespaceDecl>(CurrentNamespace->getParent ())) {
796+ if (!CurrentNamespace->isInlineNamespace ())
797+ NamespaceStack.push (CurrentNamespace);
798+ }
799+ }
800+ std::optional<api_notes::ContextID> NamespaceID;
801+ while (!NamespaceStack.empty ()) {
802+ auto CurrentNamespace = NamespaceStack.top ();
803+ NamespaceStack.pop ();
804+ NamespaceID =
805+ Reader->lookupNamespaceID (CurrentNamespace->getName (), NamespaceID);
806+ if (!NamespaceID)
807+ return std::nullopt ;
808+ }
809+ if (NamespaceID)
810+ return api_notes::Context (*NamespaceID,
811+ api_notes::ContextKind::Namespace);
812+ }
813+ }
814+ return std::nullopt ;
815+ }
816+
817+ static std::optional<api_notes::Context>
818+ UnwindTagContext (TagDecl *DC, api_notes::APINotesManager &APINotes) {
819+ assert (DC && " tag context must not be null" );
820+ for (auto Reader : APINotes.findAPINotes (DC->getLocation ())) {
821+ // Retrieve the context ID for the parent tag of the decl.
822+ std::stack<TagDecl *> TagStack;
823+ {
824+ for (auto CurrentTag = DC; CurrentTag;
825+ CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent ()))
826+ TagStack.push (CurrentTag);
827+ }
828+ assert (!TagStack.empty ());
829+ std::optional<api_notes::Context> Ctx =
830+ UnwindNamespaceContext (TagStack.top ()->getDeclContext (), APINotes);
831+ while (!TagStack.empty ()) {
832+ auto CurrentTag = TagStack.top ();
833+ TagStack.pop ();
834+ auto CtxID = Reader->lookupTagID (CurrentTag->getName (), Ctx);
835+ if (!CtxID)
836+ return std::nullopt ;
837+ Ctx = api_notes::Context (*CtxID, api_notes::ContextKind::Tag);
838+ }
839+ return Ctx;
840+ }
841+ return std::nullopt ;
842+ }
843+
786844// / Process API notes that are associated with this declaration, mapping them
787845// / to attributes as appropriate.
788846void Sema::ProcessAPINotes (Decl *D) {
789847 if (!D)
790848 return ;
791849
792- auto GetNamespaceContext =
793- [&](DeclContext *DC) -> std::optional<api_notes::Context> {
794- if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
795- for (auto Reader :
796- APINotes.findAPINotes (NamespaceContext->getLocation ())) {
797- // Retrieve the context ID for the parent namespace of the decl.
798- std::stack<NamespaceDecl *> NamespaceStack;
799- {
800- for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
801- CurrentNamespace =
802- dyn_cast<NamespaceDecl>(CurrentNamespace->getParent ())) {
803- if (!CurrentNamespace->isInlineNamespace ())
804- NamespaceStack.push (CurrentNamespace);
805- }
806- }
807- std::optional<api_notes::ContextID> NamespaceID;
808- while (!NamespaceStack.empty ()) {
809- auto CurrentNamespace = NamespaceStack.top ();
810- NamespaceStack.pop ();
811- NamespaceID = Reader->lookupNamespaceID (CurrentNamespace->getName (),
812- NamespaceID);
813- if (!NamespaceID)
814- break ;
815- }
816- if (NamespaceID)
817- return api_notes::Context (*NamespaceID,
818- api_notes::ContextKind::Namespace);
819- }
820- }
821- return std::nullopt ;
822- };
823-
824850 // Globals.
825851 if (D->getDeclContext ()->isFileContext () ||
826852 D->getDeclContext ()->isNamespace () ||
827853 D->getDeclContext ()->isExternCContext () ||
828854 D->getDeclContext ()->isExternCXXContext ()) {
829855 std::optional<api_notes::Context> APINotesContext =
830- GetNamespaceContext (D->getDeclContext ());
856+ UnwindNamespaceContext (D->getDeclContext (), APINotes );
831857 // Global variables.
832858 if (auto VD = dyn_cast<VarDecl>(D)) {
833859 for (auto Reader : APINotes.findAPINotes (D->getLocation ())) {
@@ -899,6 +925,8 @@ void Sema::ProcessAPINotes(Decl *D) {
899925 }
900926
901927 for (auto Reader : APINotes.findAPINotes (D->getLocation ())) {
928+ if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext ()))
929+ APINotesContext = UnwindTagContext (ParentTag, APINotes);
902930 auto Info = Reader->lookupTag (LookupName, APINotesContext);
903931 ProcessVersionedAPINotes (*this , Tag, Info);
904932 }
@@ -1014,23 +1042,24 @@ void Sema::ProcessAPINotes(Decl *D) {
10141042 }
10151043 }
10161044
1017- if (auto CXXRecord = dyn_cast<CXXRecordDecl>(D->getDeclContext ())) {
1018- auto GetRecordContext = [&](api_notes::APINotesReader *Reader)
1019- -> std::optional<api_notes::ContextID> {
1020- auto ParentContext = GetNamespaceContext (CXXRecord->getDeclContext ());
1021- if (auto Found = Reader->lookupTagID (CXXRecord->getName (), ParentContext))
1022- return *Found;
1023-
1024- return std::nullopt ;
1025- };
1026-
1045+ if (auto TagContext = dyn_cast<TagDecl>(D->getDeclContext ())) {
10271046 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
10281047 for (auto Reader : APINotes.findAPINotes (D->getLocation ())) {
1029- if (auto Context = GetRecordContext (Reader)) {
1030- auto Info = Reader->lookupCXXMethod (*Context, CXXMethod->getName ());
1048+ if (auto Context = UnwindTagContext (TagContext, APINotes)) {
1049+ auto Info =
1050+ Reader->lookupCXXMethod (Context->id , CXXMethod->getName ());
10311051 ProcessVersionedAPINotes (*this , CXXMethod, Info);
10321052 }
10331053 }
10341054 }
1055+
1056+ if (auto Tag = dyn_cast<TagDecl>(D)) {
1057+ for (auto Reader : APINotes.findAPINotes (D->getLocation ())) {
1058+ if (auto Context = UnwindTagContext (TagContext, APINotes)) {
1059+ auto Info = Reader->lookupTag (Tag->getName (), Context);
1060+ ProcessVersionedAPINotes (*this , Tag, Info);
1061+ }
1062+ }
1063+ }
10351064 }
10361065}
0 commit comments