Skip to content

[Clang] add fix-it hints for unknown attributes #141305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
50 changes: 30 additions & 20 deletions clang/include/clang/Basic/AttributeCommonInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H

#include "clang/Basic/AttributeScopeInfo.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TokenKinds.h"

Expand Down Expand Up @@ -61,6 +62,7 @@ class AttributeCommonInfo {
/// implicitly.
AS_Implicit
};

enum Kind {
#define PARSED_ATTR(NAME) AT_##NAME,
#include "clang/Basic/AttrParsedAttrList.inc"
Expand All @@ -78,9 +80,9 @@ class AttributeCommonInfo {

private:
const IdentifierInfo *AttrName = nullptr;
const IdentifierInfo *ScopeName = nullptr;
AttributeScopeInfo AttrScope;
SourceRange AttrRange;
const SourceLocation ScopeLoc;

// Corresponds to the Kind enum.
LLVM_PREFERRED_TYPE(Kind)
unsigned AttrKind : 16;
Expand Down Expand Up @@ -146,33 +148,31 @@ class AttributeCommonInfo {
};

AttributeCommonInfo(const IdentifierInfo *AttrName,
const IdentifierInfo *ScopeName, SourceRange AttrRange,
SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed)
: AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
ScopeLoc(ScopeLoc), AttrKind(AttrKind),
SyntaxUsed(FormUsed.getSyntax()),
AttributeScopeInfo AttrScope, SourceRange AttrRange,
Kind AttrKind, Form FormUsed)
: AttrName(AttrName), AttrScope(AttrScope), AttrRange(AttrRange),
AttrKind(AttrKind), SyntaxUsed(FormUsed.getSyntax()),
SpellingIndex(FormUsed.getSpellingIndex()),
IsAlignas(FormUsed.isAlignas()),
IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit &&
"Invalid syntax!");
}

AttributeCommonInfo(const IdentifierInfo *AttrName,
const IdentifierInfo *ScopeName, SourceRange AttrRange,
SourceLocation ScopeLoc, Form FormUsed)
AttributeCommonInfo(const IdentifierInfo *AttrName, AttributeScopeInfo Scope,
SourceRange AttrRange, Form FormUsed)
: AttributeCommonInfo(
AttrName, ScopeName, AttrRange, ScopeLoc,
getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()),
AttrName, Scope, AttrRange,
getParsedKind(AttrName, Scope.getName(), FormUsed.getSyntax()),
FormUsed) {}

AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
Form FormUsed)
: AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(),
: AttributeCommonInfo(AttrName, AttributeScopeInfo(), AttrRange,
FormUsed) {}

AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed)
: AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K,
: AttributeCommonInfo(nullptr, AttributeScopeInfo(), AttrRange, K,
FormUsed) {}

AttributeCommonInfo(AttributeCommonInfo &&) = default;
Expand All @@ -190,17 +190,27 @@ class AttributeCommonInfo {
SourceRange getRange() const { return AttrRange; }
void setRange(SourceRange R) { AttrRange = R; }

bool hasScope() const { return ScopeName; }
const IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
bool hasScope() const { return AttrScope.isValid(); }
bool isExplicitScope() const { return AttrScope.isExplicit(); }

const IdentifierInfo *getScopeName() const { return AttrScope.getName(); }
SourceLocation getScopeLoc() const { return AttrScope.getNameLoc(); }

/// Gets the normalized full name, which consists of both scope and name and
/// 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;
std::string getNormalizedFullName(StringRef ScopeName,
StringRef AttrName) const;
StringRef getNormalizedScopeName() const;
StringRef getNormalizedAttrName(StringRef ScopeName) const;

std::optional<StringRef> tryGetCorrectedScopeName(StringRef ScopeName) const;
std::optional<StringRef>
tryGetCorrectedAttrName(StringRef ScopeName, StringRef AttrName,
const TargetInfo &Target,
const LangOptions &LangOpts) const;

SourceRange getNormalizedRange() const;

bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
Expand Down
48 changes: 48 additions & 0 deletions clang/include/clang/Basic/AttributeScopeInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//==- AttributeScopeInfo.h - Base info about an Attribute Scope --*- 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 AttributeScopeInfo type, which represents information
// about the scope of an attribute.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a file header.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erichkeane Thanks for the feedback. I've added a header

#define LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H

#include "clang/Basic/SourceLocation.h"

namespace clang {

class IdentifierInfo;

class AttributeScopeInfo {
public:
AttributeScopeInfo() = default;

AttributeScopeInfo(const IdentifierInfo *Name, SourceLocation NameLoc)
: Name(Name), NameLoc(NameLoc) {}

AttributeScopeInfo(const IdentifierInfo *Name, SourceLocation NameLoc,
SourceLocation CommonScopeLoc)
: Name(Name), NameLoc(NameLoc), CommonScopeLoc(CommonScopeLoc) {}

const IdentifierInfo *getName() const { return Name; }
SourceLocation getNameLoc() const { return NameLoc; }

bool isValid() const { return Name != nullptr; }
bool isExplicit() const { return CommonScopeLoc.isInvalid(); }

private:
const IdentifierInfo *Name = nullptr;
SourceLocation NameLoc;
SourceLocation CommonScopeLoc;
};

} // namespace clang

#endif // LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H
Loading