[clang] [Clang] add typo correction for unknown attribute names (PR #140629)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 19 14:48:27 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Oleksandr T. (a-tarasyuk)
<details>
<summary>Changes</summary>
This patch enhances Clang's diagnosis for unknown attributes by providing typo correction suggestions for known attributes.
```cpp
[[gmu::deprected]] // expected-warning {{unknown attribute 'gmu::deprected' ignored; did you mean 'gnu::deprecated'?}}
int f1(void) {
return 0;
}
[[deprected]] // expected-warning {{unknown attribute 'deprected' ignored; did you mean 'deprecated'?}}
int f2(void) {
return 0;
}
```
---
Patch is 30.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140629.diff
20 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/include/clang/Basic/AttributeCommonInfo.h (+5)
- (modified) clang/include/clang/Basic/Attributes.h (+4)
- (modified) clang/include/clang/Basic/CMakeLists.txt (+6)
- (modified) clang/include/clang/Basic/DiagnosticCommonKinds.td (+2)
- (added) clang/include/clang/Basic/SimpleTypoCorrection.h (+35)
- (modified) clang/include/clang/Sema/Sema.h (+2)
- (modified) clang/lib/AST/CommentSema.cpp (+26-71)
- (modified) clang/lib/Basic/Attributes.cpp (+104-49)
- (modified) clang/lib/Basic/CMakeLists.txt (+1)
- (added) clang/lib/Basic/SimpleTypoCorrection.cpp (+52)
- (modified) clang/lib/Sema/SemaDeclAttr.cpp (+15-3)
- (modified) clang/lib/Sema/SemaType.cpp (+1-3)
- (modified) clang/test/Parser/cxx0x-attributes.cpp (+1-1)
- (modified) clang/test/Sema/attr-c2x.c (+2-2)
- (modified) clang/test/Sema/unknown-attributes.c (+13-3)
- (modified) clang/test/SemaCXX/cxx11-gnu-attrs.cpp (+1-1)
- (modified) clang/utils/TableGen/ClangAttrEmitter.cpp (+27)
- (modified) clang/utils/TableGen/TableGen.cpp (+6)
- (modified) clang/utils/TableGen/TableGenBackends.h (+2)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ac9baf229b489..deee00128c1fa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -561,6 +561,8 @@ Improvements to Clang's diagnostics
- Fixed a crash when checking a ``__thread``-specified variable declaration
with a dependent type in C++. (#GH140509)
+- Clang now suggests corrections for unknown attribute names.
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 6db7b53317e7d..b4b8345b4ed40 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -21,6 +21,8 @@ namespace clang {
class ASTRecordWriter;
class IdentifierInfo;
+class LangOptions;
+class TargetInfo;
class AttributeCommonInfo {
public:
@@ -196,6 +198,9 @@ class AttributeCommonInfo {
/// with surrounding underscores removed as appropriate (e.g.
/// __gnu__::__attr__ will be normalized to gnu::attr).
std::string getNormalizedFullName() const;
+ std::optional<std::string>
+ getCorrectedFullName(const TargetInfo &Target,
+ const LangOptions &LangOpts) const;
SourceRange getNormalizedRange() const;
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
diff --git a/clang/include/clang/Basic/Attributes.h b/clang/include/clang/Basic/Attributes.h
index 99bb668fe32d0..9cf6fb3d89019 100644
--- a/clang/include/clang/Basic/Attributes.h
+++ b/clang/include/clang/Basic/Attributes.h
@@ -19,6 +19,10 @@ class TargetInfo;
/// Return the version number associated with the attribute if we
/// recognize and implement the attribute specified by the given information.
+int hasAttribute(AttributeCommonInfo::Syntax Syntax, llvm::StringRef ScopeName,
+ llvm::StringRef AttrName, const TargetInfo &Target,
+ const LangOptions &LangOpts, bool CheckPlugins);
+
int hasAttribute(AttributeCommonInfo::Syntax Syntax,
const IdentifierInfo *Scope, const IdentifierInfo *Attr,
const TargetInfo &Target, const LangOptions &LangOpts);
diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt
index 265ea1fc06494..1873878e2e46b 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -79,6 +79,12 @@ clang_tablegen(CXX11AttributeInfo.inc -gen-cxx11-attribute-info
TARGET CXX11AttributeInfo
)
+ clang_tablegen(AttributeSpellingList.inc -gen-attribute-spelling-list
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE Attr.td
+ TARGET AttributeSpellingList
+ )
+
clang_tablegen(Builtins.inc -gen-clang-builtins
SOURCE Builtins.td
TARGET ClangBuiltins)
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index e4d94fefbbf3d..0bd8a423c393e 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -181,6 +181,8 @@ def err_opencl_unknown_type_specifier : Error<
def warn_unknown_attribute_ignored : Warning<
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_unknown_attribute_ignored_suggestion : Warning<
+ "unknown attribute %0 ignored; did you mean '%1'?">, InGroup<UnknownAttributes>;
def warn_attribute_ignored : Warning<"%0 attribute ignored">,
InGroup<IgnoredAttributes>;
def err_keyword_not_supported_on_target : Error<
diff --git a/clang/include/clang/Basic/SimpleTypoCorrection.h b/clang/include/clang/Basic/SimpleTypoCorrection.h
new file mode 100644
index 0000000000000..4cd104f79aebe
--- /dev/null
+++ b/clang/include/clang/Basic/SimpleTypoCorrection.h
@@ -0,0 +1,35 @@
+#ifndef LLVM_CLANG_BASIC_SIMPLETYPOCORRECTION_H
+#define LLVM_CLANG_BASIC_SIMPLETYPOCORRECTION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+class SimpleTypoCorrection {
+ StringRef BestCandidate;
+ StringRef Typo;
+
+ const unsigned MaxEditDistance;
+ unsigned BestEditDistance;
+ unsigned BestIndex;
+ unsigned NextIndex;
+
+public:
+ explicit SimpleTypoCorrection(StringRef Typo)
+ : BestCandidate(), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
+ BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
+
+ void add(const StringRef Candidate);
+ void add(const char *Candidate);
+ void add(const IdentifierInfo *Candidate);
+
+ std::optional<StringRef> getCorrection() const;
+ bool hasCorrection() const;
+ unsigned getCorrectionIndex() const;
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_SIMPLETYPOCORRECTION_H
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5ec67087aeea4..d7a3a81065d33 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5033,6 +5033,8 @@ class Sema final : public SemaBase {
/// which might be lying around on it.
void checkUnusedDeclAttributes(Declarator &D);
+ void DiagnoseUnknownAttribute(const ParsedAttr &AL);
+
/// DeclClonePragmaWeak - clone existing decl (maybe definition),
/// \#pragma weak needs a non-definition decl and source may not have one.
NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp
index bd2206bb8a3bc..fb745fc560d2f 100644
--- a/clang/lib/AST/CommentSema.cpp
+++ b/clang/lib/AST/CommentSema.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/DiagnosticComment.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SimpleTypoCorrection.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringSwitch.h"
@@ -975,69 +976,22 @@ unsigned Sema::resolveParmVarReference(StringRef Name,
return ParamCommandComment::InvalidParamIndex;
}
-namespace {
-class SimpleTypoCorrector {
- const NamedDecl *BestDecl;
-
- StringRef Typo;
- const unsigned MaxEditDistance;
-
- unsigned BestEditDistance;
- unsigned BestIndex;
- unsigned NextIndex;
-
-public:
- explicit SimpleTypoCorrector(StringRef Typo)
- : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
- BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
-
- void addDecl(const NamedDecl *ND);
-
- const NamedDecl *getBestDecl() const {
- if (BestEditDistance > MaxEditDistance)
- return nullptr;
-
- return BestDecl;
- }
+unsigned
+Sema::correctTypoInParmVarReference(StringRef Typo,
+ ArrayRef<const ParmVarDecl *> ParamVars) {
+ SimpleTypoCorrection STC(Typo);
+ for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
+ const ParmVarDecl *Param = ParamVars[i];
+ if (!Param)
+ continue;
- unsigned getBestDeclIndex() const {
- assert(getBestDecl());
- return BestIndex;
+ STC.add(Param->getIdentifier());
}
-};
-
-void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
- unsigned CurrIndex = NextIndex++;
-
- const IdentifierInfo *II = ND->getIdentifier();
- if (!II)
- return;
- StringRef Name = II->getName();
- unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
- if (MinPossibleEditDistance > 0 &&
- Typo.size() / MinPossibleEditDistance < 3)
- return;
+ if (STC.hasCorrection())
+ return STC.getCorrectionIndex();
- unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
- if (EditDistance < BestEditDistance) {
- BestEditDistance = EditDistance;
- BestDecl = ND;
- BestIndex = CurrIndex;
- }
-}
-} // end anonymous namespace
-
-unsigned Sema::correctTypoInParmVarReference(
- StringRef Typo,
- ArrayRef<const ParmVarDecl *> ParamVars) {
- SimpleTypoCorrector Corrector(Typo);
- for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
- Corrector.addDecl(ParamVars[i]);
- if (Corrector.getBestDecl())
- return Corrector.getBestDeclIndex();
- else
- return ParamCommandComment::InvalidParamIndex;
+ return ParamCommandComment::InvalidParamIndex;
}
namespace {
@@ -1079,16 +1033,18 @@ bool Sema::resolveTParamReference(
namespace {
void CorrectTypoInTParamReferenceHelper(
- const TemplateParameterList *TemplateParameters,
- SimpleTypoCorrector &Corrector) {
+ const TemplateParameterList *TemplateParameters,
+ SimpleTypoCorrection &STC) {
for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
const NamedDecl *Param = TemplateParameters->getParam(i);
- Corrector.addDecl(Param);
+ if (!Param)
+ continue;
+
+ STC.add(Param->getIdentifier());
if (const TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(Param))
- CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
- Corrector);
+ CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(), STC);
}
}
} // end anonymous namespace
@@ -1096,13 +1052,12 @@ void CorrectTypoInTParamReferenceHelper(
StringRef Sema::correctTypoInTParamReference(
StringRef Typo,
const TemplateParameterList *TemplateParameters) {
- SimpleTypoCorrector Corrector(Typo);
- CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
- if (const NamedDecl *ND = Corrector.getBestDecl()) {
- const IdentifierInfo *II = ND->getIdentifier();
- assert(II && "SimpleTypoCorrector should not return this decl");
- return II->getName();
- }
+ SimpleTypoCorrection STC(Typo);
+ CorrectTypoInTParamReferenceHelper(TemplateParameters, STC);
+
+ if (auto CorrectedTParamReference = STC.getCorrection())
+ return *CorrectedTParamReference;
+
return StringRef();
}
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 8ff5cc54ccc93..0c0a816c78039 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ParsedAttrInfo.h"
+#include "clang/Basic/SimpleTypoCorrection.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringMap.h"
@@ -22,30 +23,37 @@
using namespace clang;
-static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
- StringRef ScopeName, const TargetInfo &Target,
- const LangOptions &LangOpts) {
+static StringRef canonicalizeScopeName(StringRef Name) {
+ // Normalize the scope name, but only for gnu and clang attributes.
+ if (Name == "__gnu__")
+ return "gnu";
-#include "clang/Basic/AttrHasAttributeImpl.inc"
+ if (Name == "_Clang")
+ return "clang";
- return 0;
+ return Name;
}
-int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
- const IdentifierInfo *Scope, const IdentifierInfo *Attr,
- const TargetInfo &Target, const LangOptions &LangOpts,
- bool CheckPlugins) {
- StringRef Name = Attr->getName();
+static StringRef canonicalizeAttrName(StringRef Name) {
// Normalize the attribute name, __foo__ becomes foo.
if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
- Name = Name.substr(2, Name.size() - 4);
+ return Name.substr(2, Name.size() - 4);
- // Normalize the scope name, but only for gnu and clang attributes.
- StringRef ScopeName = Scope ? Scope->getName() : "";
- if (ScopeName == "__gnu__")
- ScopeName = "gnu";
- else if (ScopeName == "_Clang")
- ScopeName = "clang";
+ return Name;
+}
+
+static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
+ StringRef ScopeName, const TargetInfo &Target,
+ const LangOptions &LangOpts) {
+#include "clang/Basic/AttrHasAttributeImpl.inc"
+ return 0;
+}
+
+int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, StringRef ScopeName,
+ StringRef Name, const TargetInfo &Target,
+ const LangOptions &LangOpts, bool CheckPlugins) {
+ ScopeName = canonicalizeScopeName(ScopeName);
+ Name = canonicalizeAttrName(Name);
// As a special case, look for the omp::sequence and omp::directive
// attributes. We support those, but not through the typical attribute
@@ -72,6 +80,14 @@ int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
return 0;
}
+int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
+ const IdentifierInfo *Scope, const IdentifierInfo *Attr,
+ const TargetInfo &Target, const LangOptions &LangOpts,
+ bool CheckPlugins) {
+ return hasAttribute(Syntax, Scope ? Scope->getName() : "", Attr->getName(),
+ Target, LangOpts, CheckPlugins);
+}
+
int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
const IdentifierInfo *Scope, const IdentifierInfo *Attr,
const TargetInfo &Target, const LangOptions &LangOpts) {
@@ -90,25 +106,25 @@ const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
}
static StringRef
-normalizeAttrScopeName(const IdentifierInfo *Scope,
+normalizeAttrScopeName(StringRef ScopeName,
AttributeCommonInfo::Syntax SyntaxUsed) {
- if (!Scope)
- return "";
-
- // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
- // to be "clang".
- StringRef ScopeName = Scope->getName();
if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
- SyntaxUsed == AttributeCommonInfo::AS_C23) {
- if (ScopeName == "__gnu__")
- ScopeName = "gnu";
- else if (ScopeName == "_Clang")
- ScopeName = "clang";
- }
+ SyntaxUsed == AttributeCommonInfo::AS_C23)
+ return canonicalizeScopeName(ScopeName);
+
return ScopeName;
}
-static StringRef normalizeAttrName(const IdentifierInfo *Name,
+static StringRef
+normalizeAttrScopeName(const IdentifierInfo *ScopeName,
+ AttributeCommonInfo::Syntax SyntaxUsed) {
+ if (ScopeName)
+ return normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
+
+ return "";
+}
+
+static StringRef normalizeAttrName(StringRef AttrName,
StringRef NormalizedScopeName,
AttributeCommonInfo::Syntax SyntaxUsed) {
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
@@ -119,10 +135,9 @@ static StringRef normalizeAttrName(const IdentifierInfo *Name,
SyntaxUsed == AttributeCommonInfo::AS_C23) &&
(NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
NormalizedScopeName == "clang"));
- StringRef AttrName = Name->getName();
- if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
- AttrName.ends_with("__"))
- AttrName = AttrName.slice(2, AttrName.size() - 2);
+
+ if (ShouldNormalize)
+ return canonicalizeAttrName(AttrName);
return AttrName;
}
@@ -137,16 +152,11 @@ bool AttributeCommonInfo::isClangScope() const {
#include "clang/Sema/AttrParsedAttrKinds.inc"
-static SmallString<64> normalizeName(const IdentifierInfo *Name,
- const IdentifierInfo *Scope,
+static SmallString<64> normalizeName(StringRef AttrName, StringRef ScopeName,
AttributeCommonInfo::Syntax SyntaxUsed) {
- StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
- StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
-
- std::string StrAttrName = AttrName.str();
- if (SyntaxUsed == AttributeCommonInfo::AS_HLSLAnnotation)
- StrAttrName = AttrName.lower();
-
+ std::string StrAttrName = SyntaxUsed == AttributeCommonInfo::AS_HLSLAnnotation
+ ? AttrName.lower()
+ : AttrName.str();
SmallString<64> FullName = ScopeName;
if (!ScopeName.empty()) {
assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
@@ -154,10 +164,18 @@ static SmallString<64> normalizeName(const IdentifierInfo *Name,
FullName += "::";
}
FullName += StrAttrName;
-
return FullName;
}
+static SmallString<64> normalizeName(const IdentifierInfo *Name,
+ const IdentifierInfo *Scope,
+ AttributeCommonInfo::Syntax SyntaxUsed) {
+ StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
+ StringRef AttrName =
+ normalizeAttrName(Name->getName(), ScopeName, SyntaxUsed);
+ return normalizeName(AttrName, ScopeName, SyntaxUsed);
+}
+
AttributeCommonInfo::Kind
AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
const IdentifierInfo *ScopeName,
@@ -167,8 +185,8 @@ AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
AttributeCommonInfo::AttrArgsInfo
AttributeCommonInfo::getCXX11AttrArgsInfo(const IdentifierInfo *Name) {
- StringRef AttrName =
- normalizeAttrName(Name, /*NormalizedScopeName*/ "", Syntax::AS_CXX11);
+ StringRef AttrName = normalizeAttrName(
+ Name->getName(), /*NormalizedScopeName*/ "", Syntax::AS_CXX11);
#define CXX11_ATTR_ARGS_INFO
return llvm::StringSwitch<AttributeCommonInfo::AttrArgsInfo>(AttrName)
#include "clang/Basic/CXX11AttributeInfo.inc"
@@ -203,10 +221,47 @@ unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
// attribute spell list index matching code.
auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
StringRef ScopeName = normalizeAttrScopeName(getScopeName(), Syntax);
- StringRef Name = normalizeAttrName(getAttrName(), ScopeName, Syntax);
-
+ StringRef Name =
+ normalizeAttrName(getAttrName()->getName(), ScopeName, Syntax);
AttributeCommonInfo::Scope ComputedScope =
getScopeFromNormalizedScopeName(ScopeName);
#include "clang/Sema/AttrSpellingListIndex.inc"
}
+
+#include "clang/Basic/AttributeSpellingList.inc"
+
+std::optional<std::string>
+AttributeCommonInfo::getCorrectedFullName(const TargetInfo &Target,
+ const LangOptions &LangOpts) const {
+ StringRef ScopeName = normalizeAttrScopeName(getScopeName(), getSyntax());
+ if (ScopeName.size() > 0 &&
+ llvm::none_of(AttrScopeSpellingList,
+ [&](const char *S) { return S == ScopeName; })) {
+ SimpleTypoCorrection STC(ScopeName);
+ for (const auto &Scope : AttrScopeSpellingList)
+ STC.add(Scope);
+
+ if (auto CorrectedScopeName = STC.getCorrection())
+ ScopeName = *CorrectedScopeName;
+ }
+
+ StringRef AttrName =
+ normalizeAttrName(getAttrName()->getName(), ScopeName, getSyntax());
+ if (llvm::none_of(AttrSpellingList,
+ [&](const char *A) { return A == AttrName; })) {
+ SimpleTypoCorrection STC(AttrName);
+ for (const auto &Attr : AttrSpellingList)
+ STC.add(Attr);
+
+ if (auto CorrectedAttrName = STC.getCorrection())
+ AttrName = *CorrectedAttrName;
+ }
+
+ if (hasAttribute(getSyntax(), ScopeName, AttrName, Target, LangOpts,
+ /*CheckPlugins=*/true))
+ return static_cast<std::string>(
+ normalizeName(AttrName, ScopeName, getSyntax()));
+
+ return std::nullopt;
+}
diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index 0eacf79f5d478..f8a31c890ac4d 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -86,6 +86,7 @@ add_clang_library(clangBasic
SanitizerSpecialCaseList.cpp
Sanitizers.cpp
Sarif.cpp
+ SimpleTypoCorrection.cpp
SourceLocation.cpp
SourceManager.cpp
SourceMgrAdapter.cpp
diff --git a/clang/lib/Basic/SimpleTypoCorrection.cpp b/clang/lib/Basic/SimpleTypoCorrection.cpp
new file mode 100644
index 0000000000000..c98b89d9f080d
--- /dev/null
+++ b/clang/lib/Basic/SimpleTypoCorrection.cpp
@@ -0,0 +1,52 @@
+#include "clang/Basic/SimpleTypoCorrection.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+
+void SimpleTypoCorr...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/140629
More information about the cfe-commits
mailing list