@@ -920,6 +920,143 @@ static AccessLevel getBufferAccessLevel(const Decl *decl) {
920
920
return level;
921
921
}
922
922
923
+ SourceLoc DiagnosticEngine::getDiagnosticLocForDecl (const Decl *decl) {
924
+ if (!decl)
925
+ return SourceLoc ();
926
+
927
+ if (decl->getLoc ().isValid ())
928
+ return decl->getLoc ();
929
+
930
+ // There is no location we can point to. Pretty-print the declaration
931
+ // so we can point to it.
932
+ SourceLoc ppLoc = PrettyPrintedDeclarations[decl];
933
+ if (ppLoc.isInvalid ()) {
934
+ class TrackingPrinter : public StreamPrinter {
935
+ SmallVectorImpl<std::pair<const Decl *, uint64_t >> &Entries;
936
+ AccessLevel bufferAccessLevel;
937
+
938
+ public:
939
+ TrackingPrinter (
940
+ SmallVectorImpl<std::pair<const Decl *, uint64_t >> &Entries,
941
+ raw_ostream &OS, AccessLevel bufferAccessLevel) :
942
+ StreamPrinter (OS), Entries(Entries),
943
+ bufferAccessLevel (bufferAccessLevel) {}
944
+
945
+ void printDeclLoc (const Decl *D) override {
946
+ if (getBufferAccessLevel (D) == bufferAccessLevel)
947
+ Entries.push_back ({ D, OS.tell () });
948
+ }
949
+ };
950
+ SmallVector<std::pair<const Decl *, uint64_t >, 8 > entries;
951
+ llvm::SmallString<128 > buffer;
952
+ llvm::SmallString<128 > bufferName;
953
+ {
954
+ // The access level of the buffer we want to print. Declarations below
955
+ // this access level will be omitted from the buffer; declarations
956
+ // above it will be printed, but (except for Open declarations in the
957
+ // Public buffer) will not be recorded in PrettyPrintedDeclarations as
958
+ // the "true" SourceLoc for the declaration.
959
+ AccessLevel bufferAccessLevel = getBufferAccessLevel (decl);
960
+
961
+ // Figure out which declaration to print. It's the top-most
962
+ // declaration (not a module).
963
+ const Decl *ppDecl = decl;
964
+ auto dc = decl->getDeclContext ();
965
+
966
+ // FIXME: Horrible, horrible hackaround. We're not getting a
967
+ // DeclContext everywhere we should.
968
+ if (!dc) {
969
+ return SourceLoc ();
970
+ }
971
+
972
+ while (!dc->isModuleContext ()) {
973
+ switch (dc->getContextKind ()) {
974
+ case DeclContextKind::Module:
975
+ llvm_unreachable (" Not in a module context!" );
976
+ break ;
977
+
978
+ case DeclContextKind::FileUnit:
979
+ case DeclContextKind::TopLevelCodeDecl:
980
+ break ;
981
+
982
+ case DeclContextKind::ExtensionDecl:
983
+ ppDecl = cast<ExtensionDecl>(dc);
984
+ break ;
985
+
986
+ case DeclContextKind::GenericTypeDecl:
987
+ ppDecl = cast<GenericTypeDecl>(dc);
988
+ break ;
989
+
990
+ case DeclContextKind::SerializedLocal:
991
+ case DeclContextKind::Initializer:
992
+ case DeclContextKind::AbstractClosureExpr:
993
+ case DeclContextKind::AbstractFunctionDecl:
994
+ case DeclContextKind::SubscriptDecl:
995
+ case DeclContextKind::EnumElementDecl:
996
+ break ;
997
+ }
998
+
999
+ dc = dc->getParent ();
1000
+ }
1001
+
1002
+ // Build the module name path (in reverse), which we use to
1003
+ // build the name of the buffer.
1004
+ SmallVector<StringRef, 4 > nameComponents;
1005
+ while (dc) {
1006
+ nameComponents.push_back (cast<ModuleDecl>(dc)->getName ().str ());
1007
+ dc = dc->getParent ();
1008
+ }
1009
+
1010
+ for (unsigned i = nameComponents.size (); i; --i) {
1011
+ bufferName += nameComponents[i-1 ];
1012
+ bufferName += ' .' ;
1013
+ }
1014
+
1015
+ if (auto value = dyn_cast<ValueDecl>(ppDecl)) {
1016
+ bufferName += value->getBaseName ().userFacingName ();
1017
+ } else if (auto ext = dyn_cast<ExtensionDecl>(ppDecl)) {
1018
+ bufferName += ext->getExtendedType ().getString ();
1019
+ }
1020
+
1021
+ // If we're using a lowered access level, give the buffer a distinct
1022
+ // name.
1023
+ if (bufferAccessLevel != AccessLevel::Public) {
1024
+ assert (bufferAccessLevel < AccessLevel::Public
1025
+ && " Above-public access levels should use public buffer" );
1026
+ bufferName += " (" ;
1027
+ bufferName += getAccessLevelSpelling (bufferAccessLevel);
1028
+ bufferName += " )" ;
1029
+ }
1030
+
1031
+ // Pretty-print the declaration we've picked.
1032
+ llvm::raw_svector_ostream out (buffer);
1033
+ TrackingPrinter printer (entries, out, bufferAccessLevel);
1034
+ llvm::SaveAndRestore<bool > isPrettyPrinting (IsPrettyPrintingDecl, true );
1035
+ ppDecl->print (
1036
+ printer,
1037
+ PrintOptions::printForDiagnostics (
1038
+ bufferAccessLevel,
1039
+ decl->getASTContext ().TypeCheckerOpts .PrintFullConvention ));
1040
+ }
1041
+
1042
+ // Build a buffer with the pretty-printed declaration.
1043
+ auto bufferID = SourceMgr.addMemBufferCopy (buffer, bufferName);
1044
+ auto memBufferStartLoc = SourceMgr.getLocForBufferStart (bufferID);
1045
+
1046
+ // Go through all of the pretty-printed entries and record their
1047
+ // locations.
1048
+ for (auto entry : entries) {
1049
+ PrettyPrintedDeclarations[entry.first ] =
1050
+ memBufferStartLoc.getAdvancedLoc (entry.second );
1051
+ }
1052
+
1053
+ // Grab the pretty-printed location.
1054
+ ppLoc = PrettyPrintedDeclarations[decl];
1055
+ }
1056
+
1057
+ return ppLoc;
1058
+ }
1059
+
923
1060
Optional<DiagnosticInfo>
924
1061
DiagnosticEngine::diagnosticInfoForDiagnostic (const Diagnostic &diagnostic) {
925
1062
auto behavior = state.determineBehavior (diagnostic);
@@ -931,140 +1068,9 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
931
1068
if (loc.isInvalid () && diagnostic.getDecl ()) {
932
1069
const Decl *decl = diagnostic.getDecl ();
933
1070
// If a declaration was provided instead of a location, and that declaration
934
- // has a location we can point to, use that location.
935
- loc = decl->getLoc ();
936
-
937
- if (loc.isInvalid ()) {
938
- // There is no location we can point to. Pretty-print the declaration
939
- // so we can point to it.
940
- SourceLoc ppLoc = PrettyPrintedDeclarations[decl];
941
- if (ppLoc.isInvalid ()) {
942
- class TrackingPrinter : public StreamPrinter {
943
- SmallVectorImpl<std::pair<const Decl *, uint64_t >> &Entries;
944
- AccessLevel bufferAccessLevel;
945
-
946
- public:
947
- TrackingPrinter (
948
- SmallVectorImpl<std::pair<const Decl *, uint64_t >> &Entries,
949
- raw_ostream &OS, AccessLevel bufferAccessLevel) :
950
- StreamPrinter (OS), Entries(Entries),
951
- bufferAccessLevel (bufferAccessLevel) {}
952
-
953
- void printDeclLoc (const Decl *D) override {
954
- if (getBufferAccessLevel (D) == bufferAccessLevel)
955
- Entries.push_back ({ D, OS.tell () });
956
- }
957
- };
958
- SmallVector<std::pair<const Decl *, uint64_t >, 8 > entries;
959
- llvm::SmallString<128 > buffer;
960
- llvm::SmallString<128 > bufferName;
961
- {
962
- // The access level of the buffer we want to print. Declarations below
963
- // this access level will be omitted from the buffer; declarations
964
- // above it will be printed, but (except for Open declarations in the
965
- // Public buffer) will not be recorded in PrettyPrintedDeclarations as
966
- // the "true" SourceLoc for the declaration.
967
- AccessLevel bufferAccessLevel = getBufferAccessLevel (decl);
968
-
969
- // Figure out which declaration to print. It's the top-most
970
- // declaration (not a module).
971
- const Decl *ppDecl = decl;
972
- auto dc = decl->getDeclContext ();
973
-
974
- // FIXME: Horrible, horrible hackaround. We're not getting a
975
- // DeclContext everywhere we should.
976
- if (!dc) {
977
- return None;
978
- }
979
-
980
- while (!dc->isModuleContext ()) {
981
- switch (dc->getContextKind ()) {
982
- case DeclContextKind::Module:
983
- llvm_unreachable (" Not in a module context!" );
984
- break ;
985
-
986
- case DeclContextKind::FileUnit:
987
- case DeclContextKind::TopLevelCodeDecl:
988
- break ;
989
-
990
- case DeclContextKind::ExtensionDecl:
991
- ppDecl = cast<ExtensionDecl>(dc);
992
- break ;
993
-
994
- case DeclContextKind::GenericTypeDecl:
995
- ppDecl = cast<GenericTypeDecl>(dc);
996
- break ;
997
-
998
- case DeclContextKind::SerializedLocal:
999
- case DeclContextKind::Initializer:
1000
- case DeclContextKind::AbstractClosureExpr:
1001
- case DeclContextKind::AbstractFunctionDecl:
1002
- case DeclContextKind::SubscriptDecl:
1003
- case DeclContextKind::EnumElementDecl:
1004
- break ;
1005
- }
1006
-
1007
- dc = dc->getParent ();
1008
- }
1009
-
1010
- // Build the module name path (in reverse), which we use to
1011
- // build the name of the buffer.
1012
- SmallVector<StringRef, 4 > nameComponents;
1013
- while (dc) {
1014
- nameComponents.push_back (cast<ModuleDecl>(dc)->getName ().str ());
1015
- dc = dc->getParent ();
1016
- }
1017
-
1018
- for (unsigned i = nameComponents.size (); i; --i) {
1019
- bufferName += nameComponents[i-1 ];
1020
- bufferName += ' .' ;
1021
- }
1022
-
1023
- if (auto value = dyn_cast<ValueDecl>(ppDecl)) {
1024
- bufferName += value->getBaseName ().userFacingName ();
1025
- } else if (auto ext = dyn_cast<ExtensionDecl>(ppDecl)) {
1026
- bufferName += ext->getExtendedType ().getString ();
1027
- }
1028
-
1029
- // If we're using a lowered access level, give the buffer a distinct
1030
- // name.
1031
- if (bufferAccessLevel != AccessLevel::Public) {
1032
- assert (bufferAccessLevel < AccessLevel::Public
1033
- && " Above-public access levels should use public buffer" );
1034
- bufferName += " (" ;
1035
- bufferName += getAccessLevelSpelling (bufferAccessLevel);
1036
- bufferName += " )" ;
1037
- }
1038
-
1039
- // Pretty-print the declaration we've picked.
1040
- llvm::raw_svector_ostream out (buffer);
1041
- TrackingPrinter printer (entries, out, bufferAccessLevel);
1042
- llvm::SaveAndRestore<bool > isPrettyPrinting (
1043
- IsPrettyPrintingDecl, true );
1044
- ppDecl->print (
1045
- printer,
1046
- PrintOptions::printForDiagnostics (
1047
- bufferAccessLevel,
1048
- decl->getASTContext ().TypeCheckerOpts .PrintFullConvention ));
1049
- }
1050
-
1051
- // Build a buffer with the pretty-printed declaration.
1052
- auto bufferID = SourceMgr.addMemBufferCopy (buffer, bufferName);
1053
- auto memBufferStartLoc = SourceMgr.getLocForBufferStart (bufferID);
1054
-
1055
- // Go through all of the pretty-printed entries and record their
1056
- // locations.
1057
- for (auto entry : entries) {
1058
- PrettyPrintedDeclarations[entry.first ] =
1059
- memBufferStartLoc.getAdvancedLoc (entry.second );
1060
- }
1061
-
1062
- // Grab the pretty-printed location.
1063
- ppLoc = PrettyPrintedDeclarations[decl];
1064
- }
1065
-
1066
- loc = ppLoc;
1067
- }
1071
+ // has a location we can point to (or we can generate one), use that
1072
+ // location.
1073
+ loc = getDiagnosticLocForDecl (decl);
1068
1074
}
1069
1075
1070
1076
return DiagnosticInfo (
0 commit comments