Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------------------------

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/AttributeCommonInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace clang {

class ASTRecordWriter;
class IdentifierInfo;
class LangOptions;
class TargetInfo;

class AttributeCommonInfo {
public:
Expand Down Expand Up @@ -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; }
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/Basic/SimpleTypoCorrection.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
97 changes: 26 additions & 71 deletions clang/lib/AST/CommentSema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -1079,30 +1033,31 @@ 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

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();
}

Expand Down
Loading
Loading