Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 48 additions & 0 deletions clang/include/clang/Basic/SimpleTypoCorrection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//===- SimpleTypoCorrection.h - Basic typo correction utility -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the SimpleTypoCorrection class, which performs basic
// typo correction using string similarity based on edit distance.
//
//===----------------------------------------------------------------------===//

#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