38 changes: 3 additions & 35 deletions clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,41 +37,9 @@ class SuspiciousIncludePPCallbacks : public PPCallbacks {

SuspiciousIncludeCheck::SuspiciousIncludeCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> ImplementationFileExtensionsOption =
Options.get("ImplementationFileExtensions");
RawStringImplementationFileExtensions =
ImplementationFileExtensionsOption.value_or(
utils::defaultImplementationFileExtensions());
if (ImplementationFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringImplementationFileExtensions,
ImplementationFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid implementation file extension: '%0'")
<< RawStringImplementationFileExtensions;
}
} else
ImplementationFileExtensions = Context->getImplementationFileExtensions();

std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void SuspiciousIncludeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "ImplementationFileExtensions",
RawStringImplementationFileExtensions);
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()),
ImplementationFileExtensions(Context->getImplementationFileExtensions()) {
}

void SuspiciousIncludeCheck::registerPPCallbacks(
Expand Down
15 changes: 0 additions & 15 deletions clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,16 @@ namespace clang::tidy::bugprone {
/// #include "bar.c" // warning
/// #include "baz.h" // no diagnostic
///
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extensions should not contain
/// "." prefix) ";h;hh;hpp;hxx" by default. For extension-less header
/// files, using an empty string or leaving an empty string between ";" if
/// there are other filename extensions.
///
/// - `ImplementationFileExtensions`: likewise, a semicolon-separated list of
/// filename extensions of implementation files. "c;cc;cpp;cxx" by default.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-include.html
class SuspiciousIncludeCheck : public ClangTidyCheck {
public:
SuspiciousIncludeCheck(StringRef Name, ClangTidyContext *Context);
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;

FileExtensionsSet HeaderFileExtensions;
FileExtensionsSet ImplementationFileExtensions;

private:
StringRef RawStringHeaderFileExtensions;
StringRef RawStringImplementationFileExtensions;
};

} // namespace clang::tidy::bugprone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,6 @@ static bool isNoReturnCallStatement(const Stmt *S) {
return Func->isNoReturn();
}

static bool isLiteral(const Expr *E) {
return isa<StringLiteral, CharacterLiteral, IntegerLiteral, FloatingLiteral,
CXXBoolLiteralExpr, CXXNullPtrLiteralExpr>(E);
}

static bool isUnaryExprOfLiteral(const Expr *E) {
if (const auto *UnOp = dyn_cast<UnaryOperator>(E))
return isLiteral(UnOp->getSubExpr());
return false;
}

static bool shouldBeDefaultMemberInitializer(const Expr *Value) {
if (isLiteral(Value) || isUnaryExprOfLiteral(Value))
return true;

if (const auto *DRE = dyn_cast<DeclRefExpr>(Value))
return isa<EnumConstantDecl>(DRE->getDecl());

return false;
}

namespace {

AST_MATCHER_P(FieldDecl, indexNotLessThan, unsigned, Index) {
Expand Down Expand Up @@ -166,19 +145,7 @@ isAssignmentToMemberOf(const CXXRecordDecl *Rec, const Stmt *S,

PreferMemberInitializerCheck::PreferMemberInitializerCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IsUseDefaultMemberInitEnabled(
Context->isCheckEnabled("modernize-use-default-member-init")),
UseAssignment(
Options.get("UseAssignment",
OptionsView("modernize-use-default-member-init",
Context->getOptions().CheckOptions, Context)
.get("UseAssignment", false))) {}

void PreferMemberInitializerCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "UseAssignment", UseAssignment);
}
: ClangTidyCheck(Name, Context) {}

void PreferMemberInitializerCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(cxxConstructorDecl(hasBody(compoundStmt()),
Expand Down Expand Up @@ -230,139 +197,99 @@ void PreferMemberInitializerCheck::check(
updateAssignmentLevel(Field, InitValue, Ctor, AssignedFields);
if (!canAdvanceAssignment(AssignedFields[Field]))
continue;
const bool IsInDefaultMemberInitializer =
IsUseDefaultMemberInitEnabled && getLangOpts().CPlusPlus11 &&
Ctor->isDefaultConstructor() &&
(getLangOpts().CPlusPlus20 || !Field->isBitField()) &&
!Field->hasInClassInitializer() &&
(!isa<RecordDecl>(Class->getDeclContext()) ||
!cast<RecordDecl>(Class->getDeclContext())->isUnion()) &&
shouldBeDefaultMemberInitializer(InitValue);
if (IsInDefaultMemberInitializer) {
bool InvalidFix = false;
SourceLocation FieldEnd =
Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0,
*Result.SourceManager, getLangOpts());
InvalidFix |= FieldEnd.isInvalid() || FieldEnd.isMacroID();
SourceLocation SemiColonEnd;
if (auto NextToken = Lexer::findNextToken(
S->getEndLoc(), *Result.SourceManager, getLangOpts()))
SemiColonEnd = NextToken->getEndLoc();
else
InvalidFix = true;
auto Diag =
diag(S->getBeginLoc(), "%0 should be initialized in an in-class"
" default member initializer")
<< Field;
if (InvalidFix)
continue;
CharSourceRange StmtRange =
CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd);

SmallString<128> Insertion(
{UseAssignment ? " = " : "{",
Lexer::getSourceText(Result.SourceManager->getExpansionRange(
InitValue->getSourceRange()),
*Result.SourceManager, getLangOpts()),
UseAssignment ? "" : "}"});

Diag << FixItHint::CreateInsertion(FieldEnd, Insertion)
<< FixItHint::CreateRemoval(StmtRange);

} else {
StringRef InsertPrefix = "";
bool HasInitAlready = false;
SourceLocation InsertPos;
SourceRange ReplaceRange;
bool AddComma = false;
bool InvalidFix = false;
unsigned Index = Field->getFieldIndex();
const CXXCtorInitializer *LastInListInit = nullptr;
for (const CXXCtorInitializer *Init : Ctor->inits()) {
if (!Init->isWritten() || Init->isInClassMemberInitializer())
continue;
if (Init->getMember() == Field) {
HasInitAlready = true;
if (isa<ImplicitValueInitExpr>(Init->getInit()))
InsertPos = Init->getRParenLoc();
else {
ReplaceRange = Init->getInit()->getSourceRange();
}
break;
}
if (Init->isMemberInitializer() &&
Index < Init->getMember()->getFieldIndex()) {
InsertPos = Init->getSourceLocation();
// There are initializers after the one we are inserting, so add a
// comma after this insertion in order to not break anything.
AddComma = true;
break;
StringRef InsertPrefix = "";
bool HasInitAlready = false;
SourceLocation InsertPos;
SourceRange ReplaceRange;
bool AddComma = false;
bool InvalidFix = false;
unsigned Index = Field->getFieldIndex();
const CXXCtorInitializer *LastInListInit = nullptr;
for (const CXXCtorInitializer *Init : Ctor->inits()) {
if (!Init->isWritten() || Init->isInClassMemberInitializer())
continue;
if (Init->getMember() == Field) {
HasInitAlready = true;
if (isa<ImplicitValueInitExpr>(Init->getInit()))
InsertPos = Init->getRParenLoc();
else {
ReplaceRange = Init->getInit()->getSourceRange();
}
LastInListInit = Init;
break;
}
if (HasInitAlready) {
if (InsertPos.isValid())
InvalidFix |= InsertPos.isMacroID();
else
InvalidFix |= ReplaceRange.getBegin().isMacroID() ||
ReplaceRange.getEnd().isMacroID();
} else {
if (InsertPos.isInvalid()) {
if (LastInListInit) {
InsertPos = Lexer::getLocForEndOfToken(
LastInListInit->getRParenLoc(), 0, *Result.SourceManager,
getLangOpts());
// Inserting after the last constructor initializer, so we need a
// comma.
InsertPrefix = ", ";
} else {
InsertPos = Lexer::getLocForEndOfToken(
Ctor->getTypeSourceInfo()
->getTypeLoc()
.getAs<clang::FunctionTypeLoc>()
.getLocalRangeEnd(),
0, *Result.SourceManager, getLangOpts());

// If this is first time in the loop, there are no initializers so
// `:` declares member initialization list. If this is a
// subsequent pass then we have already inserted a `:` so continue
// with a comma.
InsertPrefix = FirstToCtorInits ? " : " : ", ";
}
}
if (Init->isMemberInitializer() &&
Index < Init->getMember()->getFieldIndex()) {
InsertPos = Init->getSourceLocation();
// There are initializers after the one we are inserting, so add a
// comma after this insertion in order to not break anything.
AddComma = true;
break;
}
LastInListInit = Init;
}
if (HasInitAlready) {
if (InsertPos.isValid())
InvalidFix |= InsertPos.isMacroID();
else
InvalidFix |= ReplaceRange.getBegin().isMacroID() ||
ReplaceRange.getEnd().isMacroID();
} else {
if (InsertPos.isInvalid()) {
if (LastInListInit) {
InsertPos =
Lexer::getLocForEndOfToken(LastInListInit->getRParenLoc(), 0,
*Result.SourceManager, getLangOpts());
// Inserting after the last constructor initializer, so we need a
// comma.
InsertPrefix = ", ";
} else {
InsertPos = Lexer::getLocForEndOfToken(
Ctor->getTypeSourceInfo()
->getTypeLoc()
.getAs<clang::FunctionTypeLoc>()
.getLocalRangeEnd(),
0, *Result.SourceManager, getLangOpts());

// If this is first time in the loop, there are no initializers so
// `:` declares member initialization list. If this is a
// subsequent pass then we have already inserted a `:` so continue
// with a comma.
InsertPrefix = FirstToCtorInits ? " : " : ", ";
}
}
InvalidFix |= InsertPos.isMacroID();
}

SourceLocation SemiColonEnd;
if (auto NextToken = Lexer::findNextToken(
S->getEndLoc(), *Result.SourceManager, getLangOpts()))
SemiColonEnd = NextToken->getEndLoc();
SourceLocation SemiColonEnd;
if (auto NextToken = Lexer::findNextToken(
S->getEndLoc(), *Result.SourceManager, getLangOpts()))
SemiColonEnd = NextToken->getEndLoc();
else
InvalidFix = true;

auto Diag = diag(S->getBeginLoc(), "%0 should be initialized in a member"
" initializer of the constructor")
<< Field;
if (InvalidFix)
continue;
StringRef NewInit = Lexer::getSourceText(
Result.SourceManager->getExpansionRange(InitValue->getSourceRange()),
*Result.SourceManager, getLangOpts());
if (HasInitAlready) {
if (InsertPos.isValid())
Diag << FixItHint::CreateInsertion(InsertPos, NewInit);
else
InvalidFix = true;

auto Diag = diag(S->getBeginLoc(), "%0 should be initialized in a member"
" initializer of the constructor")
<< Field;
if (InvalidFix)
continue;
StringRef NewInit = Lexer::getSourceText(
Result.SourceManager->getExpansionRange(InitValue->getSourceRange()),
*Result.SourceManager, getLangOpts());
if (HasInitAlready) {
if (InsertPos.isValid())
Diag << FixItHint::CreateInsertion(InsertPos, NewInit);
else
Diag << FixItHint::CreateReplacement(ReplaceRange, NewInit);
} else {
SmallString<128> Insertion({InsertPrefix, Field->getName(), "(",
NewInit, AddComma ? "), " : ")"});
Diag << FixItHint::CreateInsertion(InsertPos, Insertion,
FirstToCtorInits);
FirstToCtorInits = areDiagsSelfContained();
}
Diag << FixItHint::CreateRemoval(
CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd));
Diag << FixItHint::CreateReplacement(ReplaceRange, NewInit);
} else {
SmallString<128> Insertion({InsertPrefix, Field->getName(), "(", NewInit,
AddComma ? "), " : ")"});
Diag << FixItHint::CreateInsertion(InsertPos, Insertion,
FirstToCtorInits);
FirstToCtorInits = areDiagsSelfContained();
}
Diag << FixItHint::CreateRemoval(
CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ class PreferMemberInitializerCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

const bool IsUseDefaultMemberInitEnabled;
const bool UseAssignment;
};

} // namespace clang::tidy::cppcoreguidelines
Expand Down
22 changes: 2 additions & 20 deletions clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,8 @@ namespace clang::tidy::google::readability {

GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void GlobalNamesInHeadersCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void GlobalNamesInHeadersCheck::registerMatchers(
ast_matchers::MatchFinder *Finder) {
Expand Down
10 changes: 0 additions & 10 deletions clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,15 @@ namespace clang::tidy::google::readability {
/// Flag global namespace pollution in header files.
/// Right now it only triggers on using declarations and directives.
///
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (the filename extensions should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/google/global-names-in-headers.html
class GlobalNamesInHeadersCheck : public ClangTidyCheck {
public:
GlobalNamesInHeadersCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,8 @@ namespace clang::tidy::google::build {

UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void UnnamedNamespaceInHeaderCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void UnnamedNamespaceInHeaderCheck::registerMatchers(
ast_matchers::MatchFinder *Finder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@ namespace clang::tidy::google::build {

/// Finds anonymous namespaces in headers.
///
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extensions should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// https://google.github.io/styleguide/cppguide.html#Namespaces
///
/// Corresponding cpplint.py check name: 'build/namespaces'.
Expand All @@ -36,12 +28,10 @@ class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
7 changes: 0 additions & 7 deletions clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ namespace clang::tidy::llvm_check {
/// Finds and fixes header guards that do not adhere to LLVM style.
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/llvm/header-guard.html
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
class LLVMHeaderGuardCheck : public utils::HeaderGuardCheck {
public:
LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context);
Expand Down
39 changes: 5 additions & 34 deletions clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,16 @@ AST_MATCHER_P(NamedDecl, usesHeaderFileExtension, FileExtensionsSet,
DefinitionsInHeadersCheck::DefinitionsInHeadersCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
UseHeaderFileExtension(Options.get("UseHeaderFileExtension", true)) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void DefinitionsInHeadersCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "UseHeaderFileExtension", UseHeaderFileExtension);
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) {
auto DefinitionMatcher =
anyOf(functionDecl(isDefinition(), unless(isDeleted())),
varDecl(isDefinition()));
if (UseHeaderFileExtension) {
Finder->addMatcher(namedDecl(DefinitionMatcher,
usesHeaderFileExtension(HeaderFileExtensions))
.bind("name-decl"),
this);
} else {
Finder->addMatcher(
namedDecl(DefinitionMatcher,
anyOf(usesHeaderFileExtension(HeaderFileExtensions),
unless(isExpansionInMainFile())))
.bind("name-decl"),
this);
}
Finder->addMatcher(namedDecl(DefinitionMatcher,
usesHeaderFileExtension(HeaderFileExtensions))
.bind("name-decl"),
this);
}

void DefinitionsInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
Expand Down
9 changes: 0 additions & 9 deletions clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ namespace clang::tidy::misc {
/// The check supports these options:
/// - `UseHeaderFileExtension`: Whether to use file extension to distinguish
/// header files. True by default.
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/definitions-in-headers.html
Expand All @@ -35,13 +29,10 @@ class DefinitionsInHeadersCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus11;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
const bool UseHeaderFileExtension;
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
17 changes: 2 additions & 15 deletions clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,8 @@ static bool shouldCheckDecl(const Decl *TargetDecl) {

UnusedUsingDeclsCheck::UnusedUsingDeclsCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind("using"), this);
Expand Down
22 changes: 2 additions & 20 deletions clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,8 @@ AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }

UseAnonymousNamespaceCheck::UseAnonymousNamespaceCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void UseAnonymousNamespaceCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void UseAnonymousNamespaceCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
Expand Down
10 changes: 0 additions & 10 deletions clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ namespace clang::tidy::misc {
/// Warns when using 'static' functions or variables at global scope, and
/// suggests moving them to an anonymous namespace.
///
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/use-anonymous-namespace.html
class UseAnonymousNamespaceCheck : public ClangTidyCheck {
Expand All @@ -33,12 +25,10 @@ class UseAnonymousNamespaceCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getEnumPrefix(
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());

std::string Name = ED->getName().str();
if (std::string::npos != Name.find("enum")) {
if (StringRef(Name).contains("enum")) {
Name = Name.substr(strlen("enum"), Name.length() - strlen("enum"));
Name = Name.erase(0, Name.find_first_not_of(' '));
}
Expand Down
4 changes: 0 additions & 4 deletions clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,6 @@ class HeaderGuardPPCallbacks : public PPCallbacks {
};
} // namespace

void HeaderGuardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}

void HeaderGuardCheck::registerPPCallbacks(const SourceManager &SM,
Preprocessor *PP,
Preprocessor *ModuleExpanderPP) {
Expand Down
27 changes: 3 additions & 24 deletions clang-tools-extra/clang-tidy/utils/HeaderGuard.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,12 @@
namespace clang::tidy::utils {

/// Finds and fixes header guards.
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
class HeaderGuardCheck : public ClangTidyCheck {
public:
HeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions = HeaderFileExtensionsOption.value_or(
utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(
RawStringHeaderFileExtensions, HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;

Expand All @@ -65,7 +45,6 @@ class HeaderGuardCheck : public ClangTidyCheck {
StringRef OldGuard = StringRef()) = 0;

private:
std::string RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/SemanticHighlighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
return OMD->isClassMethod() ? HighlightingKind::StaticMethod
: HighlightingKind::Method;
if (isa<FieldDecl, ObjCPropertyDecl>(D))
if (isa<FieldDecl, IndirectFieldDecl, ObjCPropertyDecl>(D))
return HighlightingKind::Field;
if (isa<EnumDecl>(D))
return HighlightingKind::Enum;
Expand Down
16 changes: 16 additions & 0 deletions clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,22 @@ sizeof...($TemplateParameter[[Elements]]);
using $Class[[Y]]$Bracket[[<]]0$Bracket[[>]]::$Unknown_dependentName[[xxx]];
};
};
)cpp",
// Heuristically resolved IndirectFieldDecl
R"cpp(
template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]
struct $Class_def[[Base]] {
struct {
int $Field_decl[[waldo]];
};
};
template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]
struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] {
using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[waldo]];
void $Method_def[[foo]]() {
$Field_dependentName[[waldo]];
}
};
)cpp"};
for (const auto &TestCase : TestCases)
// Mask off scope modifiers to keep the tests manageable.
Expand Down
46 changes: 46 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,45 @@ New check aliases
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Improved :doc:`bugprone-suspicious-include
<clang-tidy/checks/bugprone/suspicious-include>` check by replacing the local
options `HeaderFileExtensions` and `ImplementationFileExtensions` by the
global options of the same name.

- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>`
by removing enforcement of rule `C.48
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c48-prefer-in-class-initializers-to-member-initializers-in-constructors-for-constant-initializers>`_,
which was deprecated since :program:`clang-tidy` 17. This rule is now covered
by :doc:`cppcoreguidelines-use-default-member-init
<clang-tidy/checks/cppcoreguidelines/use-default-member-init>`.

- Improved :doc:`google-build-namespaces
<clang-tidy/checks/google/build-namespaces>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`google-global-names-in-headers
<clang-tidy/checks/google/global-names-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`llvm-header-guard
<clang-tidy/checks/llvm/header-guard>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`misc-definitions-in-headers
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.
Additionally, the option `UseHeaderFileExtensions` is removed, so that the
check uses the `HeaderFileExtensions` option unconditionally.

- Improved :doc:`misc-unused-using-decls
<clang-tidy/checks/misc/unused-using-decls>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`misc-use-anonymous-namespace
<clang-tidy/checks/misc/use-anonymous-namespace>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`modernize-avoid-c-arrays
<clang-tidy/checks/modernize/avoid-c-arrays>` check by introducing the new
`AllowStringArrays` option, enabling the exclusion of array types with deduced
Expand All @@ -114,9 +153,16 @@ Changes in existing checks
Removed checks
^^^^^^^^^^^^^^

Miscellaneous
^^^^^^^^^^^^^

- Removed `cert-dcl21-cpp`, which was deprecated since :program:`clang-tidy` 17,
since the rule DCL21-CPP has been removed from the CERT guidelines.

- Fixed incorrect formatting in ``clang-apply-repalcements`` when no ``--format``
option is specified. Now ``clang-apply-replacements`` applies formatting only with
the option.

Improvements to include-fixer
-----------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,3 @@ Examples:
#include "Pterodactyl.h" // OK, .h files tend not to have definitions.
#include "Velociraptor.cpp" // Warning, filename is suspicious.
#include_next <stdio.c> // Warning, filename is suspicious.

Options
-------
.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

Default value: ``";h;hh;hpp;hxx"``
A semicolon-separated list of filename extensions of header files (the
filename extensions should not contain a "." prefix). For extension-less
header files, use an empty string or leave an empty string between ";"
if there are other filename extensions.

.. option:: ImplementationFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`ImplementationFileExtensions`.

Default value: ``"c;cc;cpp;cxx"``
Likewise, a semicolon-separated list of filename extensions of
implementation files.
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,11 @@ This check implements `C.49
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c49-prefer-initialization-to-assignment-in-constructors>`_
from the C++ Core Guidelines.

If the language version is `C++ 11` or above, the constructor is the default
constructor of the class, the field is not a bitfield (only in case of earlier
language version than `C++ 20`), furthermore the assigned value is a literal,
negated literal or ``enum`` constant then the preferred place of the
initialization is at the class member declaration.

This latter rule is `C.48
Please note, that this check does not enforce rule `C.48
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c48-prefer-in-class-initializers-to-member-initializers-in-constructors-for-constant-initializers>`_
from the C++ Core Guidelines.

Please note, that this check does not enforce this latter rule for
initializations already implemented as member initializers. For that purpose
from the C++ Core Guidelines. For that purpose
see check :doc:`modernize-use-default-member-init <../modernize/use-default-member-init>`.

.. note::

Enforcement of rule C.48 in this check is deprecated, to be removed in
:program:`clang-tidy` version 19 (only C.49 will be enforced by this check then).
Please use :doc:`cppcoreguidelines-use-default-member-init <../cppcoreguidelines/use-default-member-init>`
to enforce rule C.48.

Example 1
---------

Expand All @@ -51,16 +35,16 @@ Example 1
}
};

Here ``n`` can be initialized using a default member initializer, unlike
Here ``n`` can be initialized in the constructor initializer list, unlike
``m``, as ``m``'s initialization follows a control statement (``if``):

.. code-block:: c++

class C {
int n{1};
int n;
int m;
public:
C() {
C(): n(1) {
if (dice())
return;
m = 1;
Expand All @@ -84,7 +68,7 @@ Example 2
}
};

Here ``n`` can be initialized in the constructor initialization list, unlike
Here ``n`` can be initialized in the constructor initializer list, unlike
``m``, as ``m``'s initialization follows a control statement (``if``):

.. code-block:: c++
Expand All @@ -94,29 +78,3 @@ Here ``n`` can be initialized in the constructor initialization list, unlike
return;
m = mm;
}

.. option:: UseAssignment

Note: this option is deprecated, to be removed in :program:`clang-tidy`
version 19. Please use the `UseAssignment` option from
:doc:`cppcoreguidelines-use-default-member-init <../cppcoreguidelines/use-default-member-init>`
instead.

If this option is set to `true` (by default `UseAssignment` from
:doc:`modernize-use-default-member-init
<../modernize/use-default-member-init>` will be used),
the check will initialize members with an assignment.
In this case the fix of the first example looks like this:

.. code-block:: c++

class C {
int n = 1;
int m;
public:
C() {
if (dice())
return;
m = 1;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,3 @@ Finds anonymous namespaces in headers.
https://google.github.io/styleguide/cppguide.html#Namespaces

Corresponding cpplint.py check name: `build/namespaces`.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,3 @@ Flag global namespace pollution in header files. Right now it only triggers on

The relevant style guide section is
https://google.github.io/styleguide/cppguide.html#Namespaces.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not contain "." prefix). Default is "h".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
15 changes: 0 additions & 15 deletions clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,3 @@ llvm-header-guard
=================

Finds and fixes header guards that do not adhere to LLVM style.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
Original file line number Diff line number Diff line change
Expand Up @@ -92,27 +92,3 @@ When :program:`clang-tidy` is invoked with the `--fix-notes` option, this check
provides fixes that automatically add the ``inline`` keyword to discovered
functions. Please note that the addition of the ``inline`` keyword to variables
is not currently supported by this check.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).

.. option:: UseHeaderFileExtension

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. The check will unconditionally use the global option
`HeaderFileExtensions`.

When `true`, the check will use the file extension to distinguish header
files. Default is `true`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Finds unused ``using`` declarations.

Unused ``using``` declarations in header files will not be diagnosed since these
using declarations are part of the header's public API. Allowed header file
extensions can be configured via the `HeaderFileExtensions` option (see below).
extensions can be configured via the global option `HeaderFileExtensions`.

Example:

Expand All @@ -16,17 +16,3 @@ Example:
// main.cpp
namespace n { class C; }
using n::C; // Never actually used.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A semicolon-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For extension-less header files, use an empty string or leave an
empty string between "," if there are other filename extensions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The following uses of ``static`` will *not* be diagnosed:

* Functions or variables in header files, since anonymous namespaces in headers
is considered an antipattern. Allowed header file extensions can be configured
via the `HeaderFileExtensions` option (see below).
via the global option `HeaderFileExtensions`.
* ``const`` or ``constexpr`` variables, since they already have implicit internal
linkage in C++.

Expand All @@ -33,18 +33,4 @@ Examples:
int x;
} // namespace

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A semicolon-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is ";h;hh;hpp;hxx".
For extension-less header files, using an empty string or leaving an
empty string between ";" if there are other filename extensions.

[1] `Undeprecating static <https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012>`_
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <string>
// CHECK: #include <string>
// CHECK-NEXT: #include <memory>
// CHECK-NEXT: #include "bar.h"
#include <memory>
#include "foo.h"
#include "bar.h"

void foo() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
MainSourceFile: no.cpp
Diagnostics:
- DiagnosticName: test-header-format
DiagnosticMessage:
Message: Fix
FilePath: $(path)/no.cpp
FileOffset: 36
Replacements:
- FilePath: $(path)/no.cpp
Offset: 36
Length: 17
ReplacementText: ""
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <string>
// CHECK: #include "bar.h"
// CHECK-NEXT: #include <memory>
// CHECK-NEXT: #include <string>
#include <memory>
#include "foo.h"
#include "bar.h"

void foo() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
MainSourceFile: yes.cpp
Diagnostics:
- DiagnosticName: test-header-format
DiagnosticMessage:
Message: Fix
FilePath: $(path)/yes.cpp
FileOffset: 36
Replacements:
- FilePath: $(path)/yes.cpp
Offset: 36
Length: 17
ReplacementText: ""
...
13 changes: 13 additions & 0 deletions clang-tools-extra/test/clang-apply-replacements/format-header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: mkdir -p %T/Inputs/format_header_yes
// RUN: mkdir -p %T/Inputs/format_header_no
//
//
// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/yes.cpp > %T/Inputs/format_header_yes/yes.cpp
// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/no.cpp > %T/Inputs/format_header_no/no.cpp
// RUN: sed "s#\$(path)#%/T/Inputs/format_header_yes#" %S/Inputs/format_header/yes.yaml > %T/Inputs/format_header_yes/yes.yaml
// RUN: sed "s#\$(path)#%/T/Inputs/format_header_no#" %S/Inputs/format_header/no.yaml > %T/Inputs/format_header_no/no.yaml
// RUN: clang-apply-replacements -format -style="{BasedOnStyle: llvm, SortIncludes: CaseSensitive}" %T/Inputs/format_header_yes
// RUN: clang-apply-replacements %T/Inputs/format_header_no
// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_yes/yes.cpp %S/Inputs/format_header/yes.cpp
// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_no/no.cpp %S/Inputs/format_header/no.cpp
//
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown -x c++ -fsigned-char

// RUN: %check_clang_tidy -std=c99 %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown -x c -funsigned-char
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown-x c++ -funsigned-char
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64 c++ -funsigned-char

long t0(char a, char b) {
return a * b;
Expand Down

This file was deleted.

This file was deleted.

30 changes: 28 additions & 2 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1537,8 +1537,10 @@ the configuration (without a prefix: ``Auto``).
Possible values:

* ``RTBS_None`` (in configuration: ``None``)
Break after return type automatically.
``PenaltyReturnTypeOnItsOwnLine`` is taken into account.
This is **deprecated**. See ``Automatic`` below.

* ``RTBS_Automatic`` (in configuration: ``Automatic``)
Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``.

.. code-block:: c++

Expand All @@ -1547,6 +1549,22 @@ the configuration (without a prefix: ``Auto``).
};
int f();
int f() { return 1; }
int
LongName::AnotherLongName();

* ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``)
Same as ``Automatic`` above, except that there is no break after short
return types.

.. code-block:: c++

class A {
int f() { return 0; };
};
int f();
int f() { return 1; }
int LongName::
AnotherLongName();

* ``RTBS_All`` (in configuration: ``All``)
Always break after the return type.
Expand All @@ -1565,6 +1583,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_TopLevel`` (in configuration: ``TopLevel``)
Always break after the return types of top-level functions.
Expand All @@ -1580,6 +1600,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``)
Always break after the return type of function definitions.
Expand All @@ -1597,6 +1619,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``)
Always break after the return type of top-level definitions.
Expand All @@ -1611,6 +1635,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();



Expand Down
1 change: 1 addition & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,7 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_const`` (C++, Embarcadero)
* ``__is_constructible`` (C++, MSVC 2013)
* ``__is_convertible`` (C++, Embarcadero)
* ``__is_nothrow_convertible`` (C++, GNU)
* ``__is_convertible_to`` (Microsoft):
Synonym for ``__is_convertible``.
* ``__is_destructible`` (C++, MSVC 2013)
Expand Down
13 changes: 13 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Improvements to Clang's diagnostics
prints.

- Clang now diagnoses member template declarations with multiple declarators.
- Clang now diagnoses use of the ``template`` keyword after declarative nested name specifiers.

Improvements to Clang's time-trace
----------------------------------
Expand All @@ -160,6 +161,9 @@ Bug Fixes in This Version

- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 <https://github.com/llvm/llvm-project/issues/79435>`_).

- Clang now accepts qualified partial/explicit specializations of variable templates that
are not nominable in the lookup context of the specialization.

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -186,8 +190,17 @@ Bug Fixes to C++ Support
- Fix for crash when using a erroneous type in a return statement.
Fixes (`#63244 <https://github.com/llvm/llvm-project/issues/63244>`_)
and (`#79745 <https://github.com/llvm/llvm-project/issues/79745>`_)
- Fixed an out-of-bounds error caused by building a recovery expression for ill-formed
function calls while substituting into constraints.
(`#58548 <https://github.com/llvm/llvm-project/issues/58548>`_)
- Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
- Fix crash and diagnostic with const qualified member operator new.
Fixes (`#79748 <https://github.com/llvm/llvm-project/issues/79748>`_)
- Fix a crash when specializing an out-of-line member function with a default
parameter where we did an incorrect specialization of the initialization of
the default parameter.
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
32 changes: 22 additions & 10 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,9 @@ Controlling Diagnostics via Pragmas
Clang can also control what diagnostics are enabled through the use of
pragmas in the source code. This is useful for turning off specific
warnings in a section of source code. Clang supports GCC's pragma for
compatibility with existing source code, as well as several extensions.
compatibility with existing source code, so ``#pragma GCC diagnostic``
and ``#pragma clang diagnostic`` are synonyms for Clang. GCC will ignore
``#pragma clang diagnostic``, though.

The pragma may control any warning that can be used from the command
line. Warnings may be set to ignored, warning, error, or fatal. The
Expand All @@ -1143,8 +1145,7 @@ warnings:
#pragma GCC diagnostic ignored "-Wall"
In addition to all of the functionality provided by GCC's pragma, Clang
also allows you to push and pop the current warning state. This is
Clang also allows you to push and pop the current warning state. This is
particularly useful when writing a header file that will be compiled by
other people, because you don't know what warning flags they build with.

Expand All @@ -1157,23 +1158,34 @@ existed.
#if foo
#endif foo // warning: extra tokens at end of #endif directive
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wextra-tokens"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra-tokens"
#if foo
#endif foo // no warning
#pragma clang diagnostic pop
#pragma GCC diagnostic pop
The push and pop pragmas will save and restore the full diagnostic state
of the compiler, regardless of how it was set. That means that it is
possible to use push and pop around GCC compatible diagnostics and Clang
will push and pop them appropriately, while GCC will ignore the pushes
and pops as unknown pragmas. It should be noted that while Clang
of the compiler, regardless of how it was set. It should be noted that while Clang
supports the GCC pragma, Clang and GCC do not support the exact same set
of warnings, so even when using GCC compatible #pragmas there is no
guarantee that they will have identical behaviour on both compilers.

Clang also doesn't yet support GCC behavior for ``#pragma diagnostic pop``
that doesn't have a corresponding ``#pragma diagnostic push``. In this case
GCC pretends that there is a ``#pragma diagnostic push`` at the very beginning
of the source file, so "unpaired" ``#pragma diagnostic pop`` matches that
implicit push. This makes a difference for ``#pragma GCC diagnostic ignored``
which are not guarded by push and pop. Refer to
`GCC documentation <https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html>`_
for details.

Like GCC, Clang accepts ``ignored``, ``warning``, ``error``, and ``fatal``
severity levels. They can be used to change severity of a particular diagnostic
for a region of source file. A notable difference from GCC is that diagnostic
not enabled via command line arguments can't be enabled this way yet.

In addition to controlling warnings and errors generated by the compiler, it is
possible to generate custom warning and error messages through the following
pragmas:
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ class TypeLoc {
/// pointer types, but not through decltype or typedefs.
AutoTypeLoc getContainedAutoTypeLoc() const;

/// Get the SourceLocation of the template keyword (if any).
SourceLocation getTemplateKeywordLoc() const;

/// Initializes this to state that every location in this
/// type is the given location.
///
Expand Down Expand Up @@ -1691,7 +1694,7 @@ class TemplateSpecializationTypeLoc :
}

void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setTemplateKeywordLoc(Loc);
setTemplateKeywordLoc(SourceLocation());
setTemplateNameLoc(Loc);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ BUILTIN(__builtin_amdgcn_mqsad_u32_u8, "V4UiWUiUiV4Ui", "nc")
//===----------------------------------------------------------------------===//

TARGET_BUILTIN(__builtin_amdgcn_ballot_w32, "ZUib", "nc", "wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_ballot_w64, "WUib", "nc", "wavefrontsize64")
BUILTIN(__builtin_amdgcn_ballot_w64, "WUib", "nc")

// Deprecated intrinsics in favor of __builtin_amdgn_ballot_{w32|w64}
BUILTIN(__builtin_amdgcn_uicmp, "WUiUiUiIi", "nc")
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ ENUM_CODEGENOPT(InlineAsmDialect, InlineAsmDialectKind, 1, IAD_ATT)
CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
///< are required.
CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled.
CODEGENOPT(BBAddrMap , 1, 0) ///< Set when -fbasic-block-address-map is enabled.
CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
///< enabled.
CODEGENOPT(InstrumentFunctionsAfterInlining , 1, 0) ///< Set when
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def err_drv_hipspv_no_hip_path : Error<
"'--hip-path' must be specified when offloading to "
"SPIR-V%select{| unless %1 is given}0.">;

// TODO: Remove when COV6 is fully supported by ROCm.
def warn_drv_amdgpu_cov6: Warning<
"code object v6 is still in development and not ready for production use yet;"
" use at your own risk">;
def err_drv_undetermined_gpu_arch : Error<
"cannot determine %0 architecture: %1; consider passing it via "
"'%2'">;
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3711,6 +3711,12 @@ def err_sme_za_call_no_za_state : Error<
"call to a shared ZA function requires the caller to have ZA state">;
def err_sme_zt0_call_no_zt0_state : Error<
"call to a shared ZT0 function requires the caller to have ZT0 state">;
def err_sme_unimplemented_za_save_restore : Error<
"call to a function that shares state other than 'za' from a "
"function that has live 'za' state requires a spill/fill of ZA, which is not yet "
"implemented">;
def note_sme_use_preserves_za : Note<
"add '__arm_preserves(\"za\")' to the callee if it preserves ZA">;
def err_sme_definition_using_sm_in_non_sme_target : Error<
"function executed in streaming-SVE mode requires 'sme'">;
def err_sme_definition_using_za_in_non_sme_target : Error<
Expand Down Expand Up @@ -8241,6 +8247,9 @@ def err_invalid_declarator_in_block : Error<
"definition or redeclaration of %0 not allowed inside a block">;
def err_not_tag_in_scope : Error<
"no %select{struct|interface|union|class|enum}0 named %1 in %2">;
def ext_template_after_declarative_nns : ExtWarn<
"'template' cannot be used after a declarative nested name specifier">,
InGroup<DiagGroup<"template-in-declaration-name">>;

def err_no_typeid_with_fno_rtti : Error<
"use of typeid requires -frtti">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
// Embarcadero Binary Type Traits
TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
TYPE_TRAIT_2(__is_nothrow_convertible, IsNothrowConvertible, KEYCXX)
ARRAY_TYPE_TRAIT(__array_rank, ArrayRank, KEYCXX)
ARRAY_TYPE_TRAIT(__array_extent, ArrayExtent, KEYCXX)
// Name for GCC 6 compatibility.
Expand Down
31 changes: 31 additions & 0 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -1730,12 +1730,28 @@ let ManualCodegen = [{
defm vfwnmacc : RVVFloatingWidenTerBuiltinSetRoundingMode;
defm vfwmsac : RVVFloatingWidenTerBuiltinSetRoundingMode;
defm vfwnmsac : RVVFloatingWidenTerBuiltinSetRoundingMode;

// Vector BF16 widening multiply-accumulate
let Log2LMUL = [-2, -1, 0, 1, 2],
RequiredFeatures = ["Zvfbfwma"],
HasMaskedOffOperand = false in
defm vfwmaccbf16 : RVVOutOp1Op2BuiltinSet<"vfwmaccbf16", "y",
[["vv", "Fw", "FwFwvvu"],
["vf", "Fw", "FwFwevu"]]>;
}
// 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
defm vfwmacc : RVVFloatingWidenTerBuiltinSet;
defm vfwnmacc : RVVFloatingWidenTerBuiltinSet;
defm vfwmsac : RVVFloatingWidenTerBuiltinSet;
defm vfwnmsac : RVVFloatingWidenTerBuiltinSet;

// Vector BF16 widening multiply-accumulate
let Log2LMUL = [-2, -1, 0, 1, 2],
RequiredFeatures = ["Zvfbfwma"],
HasMaskedOffOperand = false in
defm vfwmaccbf16 : RVVOutOp1Op2BuiltinSet<"vfwmaccbf16", "y",
[["vv", "Fw", "FwFwvv"],
["vf", "Fw", "FwFwev"]]>;
}

}
Expand Down Expand Up @@ -1883,6 +1899,11 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">;
def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">;
}

// Zvfbfmin - Vector convert BF16 to FP32
let Log2LMUL = [-2, -1, 0, 1, 2] in
def vfwcvtbf16_f_f_v : RVVConvBuiltin<"Fw", "Fwv", "y", "vfwcvtbf16_f">;

let ManualCodegen = [{
{
// LLVM intrinsic
Expand Down Expand Up @@ -1970,6 +1991,11 @@ let ManualCodegen = [{
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vwu"]]>;
}
}

// Zvfbfmin - Vector convert FP32 to BF16
let Log2LMUL = [-2, -1, 0, 1, 2],
OverloadedName = "vfncvtbf16_f" in
defm : RVVConvBuiltinSet<"vfncvtbf16_f_f_w", "y", [["v", "vFwu"]]>;
}

// 13.17. Single-Width Floating-Point/Integer Type-Convert Instructions
Expand Down Expand Up @@ -2015,6 +2041,11 @@ let ManualCodegen = [{
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vw"]]>;
}
}

// Zvfbfmin - Vector convert FP32 to BF16
let Log2LMUL = [-2, -1, 0, 1, 2],
OverloadedName = "vfncvtbf16_f" in
defm : RVVConvBuiltinSet<"vfncvtbf16_f_f_w", "y", [["v", "vFw"]]>;
}
}

Expand Down
12 changes: 8 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3988,6 +3988,10 @@ defm function_sections : BoolFOption<"function-sections",
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Place each function in its own section">,
NegFlag<SetFalse>>;
defm basic_block_address_map : BoolFOption<"basic-block-address-map",
CodeGenOpts<"BBAddrMap">, DefaultFalse,
PosFlag<SetTrue, [], [CC1Option], "Emit the basic block address map section.">,
NegFlag<SetFalse>>;
def fbasic_block_sections_EQ : Joined<["-"], "fbasic-block-sections=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CC1AsOption]>,
HelpText<"Place each function's basic blocks in unique sections (ELF Only)">,
Expand Down Expand Up @@ -4797,9 +4801,9 @@ defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",
def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group<m_Group>,
HelpText<"Specify code object ABI version. Defaults to 5. (AMDGPU only)">,
Visibility<[ClangOption, FlangOption, CC1Option, FC1Option]>,
Values<"none,4,5">,
Values<"none,4,5,6">,
NormalizedValuesScope<"llvm::CodeObjectVersionKind">,
NormalizedValues<["COV_None", "COV_4", "COV_5"]>,
NormalizedValues<["COV_None", "COV_4", "COV_5", "COV_6"]>,
MarshallingInfoEnum<TargetOpts<"CodeObjectVersion">, "COV_5">;

defm cumode : SimpleMFlag<"cumode",
Expand Down Expand Up @@ -4990,10 +4994,10 @@ def mno_fmv : Flag<["-"], "mno-fmv">, Group<f_clang_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Disable function multiversioning">;
def moutline_atomics : Flag<["-"], "moutline-atomics">, Group<f_clang_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
HelpText<"Generate local calls to out-of-line atomic operations">;
def mno_outline_atomics : Flag<["-"], "mno-outline-atomics">, Group<f_clang_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
HelpText<"Don't generate local calls to out-of-line atomic operations">;
def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
HelpText<"Don't generate implicit floating point or vector instructions">;
Expand Down
29 changes: 26 additions & 3 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -914,16 +914,31 @@ struct FormatStyle {
/// Different ways to break after the function definition or
/// declaration return type.
enum ReturnTypeBreakingStyle : int8_t {
/// Break after return type automatically.
/// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account.
/// This is **deprecated**. See ``Automatic`` below.
RTBS_None,
/// Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``.
/// \code
/// class A {
/// int f() { return 0; };
/// };
/// int f();
/// int f() { return 1; }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_None,
RTBS_Automatic,
/// Same as ``Automatic`` above, except that there is no break after short
/// return types.
/// \code
/// class A {
/// int f() { return 0; };
/// };
/// int f();
/// int f() { return 1; }
/// int LongName::
/// AnotherLongName();
/// \endcode
RTBS_ExceptShortType,
/// Always break after the return type.
/// \code
/// class A {
Expand All @@ -938,6 +953,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_All,
/// Always break after the return types of top-level functions.
Expand All @@ -951,6 +968,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_TopLevel,
/// Always break after the return type of function definitions.
Expand All @@ -966,6 +985,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_AllDefinitions,
/// Always break after the return type of top-level definitions.
Expand All @@ -978,6 +999,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_TopLevelDefinitions,
};
Expand Down
15 changes: 13 additions & 2 deletions clang/include/clang/Rewrite/Core/HTMLRewrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ class RewriteBuffer;
class Preprocessor;

namespace html {
struct RelexRewriteCache;
using RelexRewriteCacheRef = std::shared_ptr<RelexRewriteCache>;

/// If you need to rewrite the same file multiple times, you can instantiate
/// a RelexRewriteCache and refer functions such as SyntaxHighlight()
/// and HighlightMacros() to it so that to avoid re-lexing the file each time.
/// The cache may outlive the rewriter as long as cached FileIDs and source
/// locations continue to make sense for the translation unit as a whole.
RelexRewriteCacheRef instantiateRelexRewriteCache();

/// HighlightRange - Highlight a range in the source code with the specified
/// start/end tags. B/E must be in the same file. This ensures that
Expand Down Expand Up @@ -67,13 +76,15 @@ namespace html {

/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
/// information about keywords, comments, etc.
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP);
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP,
RelexRewriteCacheRef Cache = nullptr);

/// HighlightMacros - This uses the macro table state from the end of the
/// file, to reexpand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP);
void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP,
RelexRewriteCacheRef Cache = nullptr);

} // end html namespace
} // end clang namespace
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2960,7 +2960,8 @@ class Sema final {
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name, SourceLocation Loc,
bool IsTemplateId);
TemplateIdAnnotation *TemplateId,
bool IsMemberSpecialization);
void
diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation FallbackLoc,
Expand Down Expand Up @@ -8456,7 +8457,7 @@ class Sema final {
SourceLocation RAngleLoc);

DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI,
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization);

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@ enum RVVRequire : uint32_t {
RVV_REQ_Zvknhb = 1 << 13,
RVV_REQ_Zvksed = 1 << 14,
RVV_REQ_Zvksh = 1 << 15,
RVV_REQ_Experimental = 1 << 16,
RVV_REQ_Zvfbfwma = 1 << 16,
RVV_REQ_Experimental = 1 << 17,

LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Experimental)
};
Expand Down
64 changes: 56 additions & 8 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
switch (CE->getCastKind()) {

case CK_LValueToRValue: {
if (DiscardResult)
return this->discard(SubExpr);

return dereference(
SubExpr, DerefKind::Read,
[](PrimType) {
Expand All @@ -86,9 +89,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
},
[this, CE](PrimType T) {
// Pointer on stack - dereference it.
if (!this->emitLoadPop(T, CE))
return false;
return DiscardResult ? this->emitPop(T, CE) : true;
return this->emitLoadPop(T, CE);
});
}

Expand Down Expand Up @@ -190,7 +191,14 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_NonAtomicToAtomic:
case CK_NoOp:
case CK_UserDefinedConversion:
return this->delegate(SubExpr);

case CK_BitCast:
if (CE->getType()->isAtomicType()) {
if (!this->discard(SubExpr))
return false;
return this->emitInvalidCast(CastKind::Reinterpret, CE);
}
return this->delegate(SubExpr);

case CK_IntegralToBoolean:
Expand Down Expand Up @@ -1121,7 +1129,7 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
if (DiscardResult)
return this->discard(Base);

if (!this->visit(Base))
if (!this->delegate(Base))
return false;

// Base above gives us a pointer on the stack.
Expand Down Expand Up @@ -1609,8 +1617,10 @@ bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
return this->emitGetPtrLocal(*LocalIndex, E);
}
} else {
const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();

if (std::optional<unsigned> LocalIndex =
allocateLocal(SubExpr, /*IsExtended=*/true)) {
allocateLocal(Inner, /*IsExtended=*/true)) {
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
return this->visitInitializer(SubExpr);
Expand Down Expand Up @@ -1668,7 +1678,9 @@ template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
if (DiscardResult)
return true;
return this->emitConstBool(E->getValue(), E);
if (E->getType()->isBooleanType())
return this->emitConstBool(E->getValue(), E);
return this->emitConst(E->getValue(), E);
}

template <class Emitter>
Expand Down Expand Up @@ -1929,10 +1941,32 @@ bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *E) {
QualType Ty = E->getType();

if (Ty->isVoidType())
if (DiscardResult || Ty->isVoidType())
return true;

return this->visitZeroInitializer(classifyPrim(Ty), Ty, E);
if (std::optional<PrimType> T = classify(Ty))
return this->visitZeroInitializer(*T, Ty, E);

assert(Ty->isAnyComplexType());
if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
}

// Initialize both fields to 0.
QualType ElemQT = Ty->getAs<ComplexType>()->getElementType();
PrimType ElemT = classifyPrim(ElemQT);

for (unsigned I = 0; I != 2; ++I) {
if (!this->visitZeroInitializer(ElemT, ElemQT, E))
return false;
if (!this->emitInitElem(ElemT, I, E))
return false;
}
return true;
}

template <class Emitter>
Expand All @@ -1946,6 +1980,20 @@ bool ByteCodeExprGen<Emitter>::VisitGenericSelectionExpr(
return this->delegate(E->getResultExpr());
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitChooseExpr(const ChooseExpr *E) {
return this->delegate(E->getChosenSubExpr());
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitObjCBoolLiteralExpr(
const ObjCBoolLiteralExpr *E) {
if (DiscardResult)
return true;

return this->emitConst(E->getValue(), E);
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
bool VisitGenericSelectionExpr(const GenericSelectionExpr *E);
bool VisitChooseExpr(const ChooseExpr *E);
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E);

protected:
bool visitExpr(const Expr *E) override;
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S) const {
const auto *CAT =
cast<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe());
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);

return true;
}

void EvaluationResult::dump() const {
Expand Down Expand Up @@ -186,9 +184,12 @@ void EvaluationResult::dump() const {
OS << "\n";
break;
}

default:
llvm_unreachable("Can't print that.");
case Invalid:
OS << "Invalid\n";
break;
case Valid:
OS << "Valid\n";
break;
}
}

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
return false;
if (!CheckDummy(S, OpPC, Ptr))
return false;
if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2020,8 +2020,11 @@ inline bool Invalid(InterpState &S, CodePtr OpPC) {
/// Same here, but only for casts.
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);

// FIXME: Support diagnosing other invalid cast kinds.
if (Kind == CastKind::Reinterpret)
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
return false;
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
break;
case Builtin::BI__builtin_assume:
case Builtin::BI__assume:
break;
case Builtin::BI__builtin_strcmp:
if (!interp__builtin_strcmp(S, OpPC, Frame))
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/PrimType.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ enum PrimType : unsigned {

enum class CastKind : uint8_t {
Reinterpret,
Atomic,
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
interp::CastKind CK) {
switch (CK) {
case interp::CastKind::Reinterpret:
OS << "reinterpret_cast";
break;
case interp::CastKind::Atomic:
OS << "atomic";
break;
}
return OS;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3854,6 +3854,12 @@ PackIndexingType::computeDependence(QualType Pattern, Expr *IndexExpr,

if (!(IndexD & TypeDependence::UnexpandedPack))
TD &= ~TypeDependence::UnexpandedPack;

// If the pattern does not contain an unexpended pack,
// the type is still dependent, and invalid
if (!Pattern->containsUnexpandedParameterPack())
TD |= TypeDependence::Error | TypeDependence::DependentInstantiation;

return TD;
}

Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/TypeLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,3 +738,12 @@ AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
return AutoTypeLoc();
return Res.getAs<AutoTypeLoc>();
}

SourceLocation TypeLoc::getTemplateKeywordLoc() const {
if (const auto TSTL = getAsAdjusted<TemplateSpecializationTypeLoc>())
return TSTL.getTemplateKeywordLoc();
if (const auto DTSTL =
getAsAdjusted<DependentTemplateSpecializationTypeLoc>())
return DTSTL.getTemplateKeywordLoc();
return SourceLocation();
}
6 changes: 3 additions & 3 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,10 +1195,10 @@ void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {

void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,
raw_ostream &OS) {
if (T->isInstantiationDependentType())
OS << T->getPattern() << "...[" << T->getIndexExpr() << "]";
else
if (T->hasSelectedType())
OS << T->getSelectedType();
else
OS << T->getPattern() << "...[" << T->getIndexExpr() << "]";
spaceBeforePlaceHolder(OS);
}

Expand Down
51 changes: 47 additions & 4 deletions clang/lib/Analysis/ReachableCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
Expand Down Expand Up @@ -453,26 +454,68 @@ bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
return isDeadRoot;
}

static bool isValidDeadStmt(const Stmt *S) {
// Check if the given `DeadStmt` is a coroutine statement and is a substmt of
// the coroutine statement. `Block` is the CFGBlock containing the `DeadStmt`.
static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {
// The coroutine statement, co_return, co_await, or co_yield.
const Stmt *CoroStmt = nullptr;
// Find the first coroutine statement after the DeadStmt in the block.
bool AfterDeadStmt = false;
for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E;
++I)
if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
if (S == DeadStmt)
AfterDeadStmt = true;
if (AfterDeadStmt &&
// For simplicity, we only check simple coroutine statements.
(llvm::isa<CoreturnStmt>(S) || llvm::isa<CoroutineSuspendExpr>(S))) {
CoroStmt = S;
break;
}
}
if (!CoroStmt)
return false;
struct Checker : RecursiveASTVisitor<Checker> {
const Stmt *DeadStmt;
bool CoroutineSubStmt = false;
Checker(const Stmt *S) : DeadStmt(S) {}
bool VisitStmt(const Stmt *S) {
if (S == DeadStmt)
CoroutineSubStmt = true;
return true;
}
// Statements captured in the CFG can be implicit.
bool shouldVisitImplicitCode() const { return true; }
};
Checker checker(DeadStmt);
checker.TraverseStmt(const_cast<Stmt *>(CoroStmt));
return checker.CoroutineSubStmt;
}

static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) {
if (S->getBeginLoc().isInvalid())
return false;
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
return BO->getOpcode() != BO_Comma;
return true;
// Coroutine statements are never considered dead statements, because removing
// them may change the function semantic if it is the only coroutine statement
// of the coroutine.
return !isInCoroutineStmt(S, Block);
}

const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
if (isValidDeadStmt(S))
if (isValidDeadStmt(S, Block))
return S;
}

CFGTerminator T = Block->getTerminator();
if (T.isStmtBranch()) {
const Stmt *S = T.getStmt();
if (S && isValidDeadStmt(S))
if (S && isValidDeadStmt(S, Block))
return S;
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Basic/Sarif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ static std::string percentEncodeURICharacter(char C) {
// should be written out directly. Otherwise, percent
// encode the character and write that out instead of the
// reserved character.
if (llvm::isAlnum(C) ||
StringRef::npos != StringRef("-._~:@!$&'()*+,;=").find(C))
if (llvm::isAlnum(C) || StringRef("-._~:@!$&'()*+,;=").contains(C))
return std::string(&C, 1);
return "%" + llvm::toHex(StringRef(&C, 1));
}
Expand Down
32 changes: 31 additions & 1 deletion clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,11 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,

Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");

// These macros are set when Clang can parse declarations with these
// attributes.
Builder.defineMacro("__ARM_STATE_ZA", "1");
Builder.defineMacro("__ARM_STATE_ZT0", "1");

// 0xe implies support for half, single and double precision operations.
if (FPU & FPUMode)
Builder.defineMacro("__ARM_FP", "0xE");
Expand Down Expand Up @@ -430,6 +435,17 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasSVE2 && HasSVE2SM4)
Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");

if (HasSME) {
Builder.defineMacro("__ARM_FEATURE_SME");
Builder.defineMacro("__ARM_FEATURE_LOCALLY_STREAMING", "1");
}

if (HasSME2) {
Builder.defineMacro("__ARM_FEATURE_SME");
Builder.defineMacro("__ARM_FEATURE_SME2");
Builder.defineMacro("__ARM_FEATURE_LOCALLY_STREAMING", "1");
}

if (HasCRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");

Expand Down Expand Up @@ -692,6 +708,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Case("sve2-sha3", FPU & SveMode && HasSVE2SHA3)
.Case("sve2-sm4", FPU & SveMode && HasSVE2SM4)
.Case("sme", HasSME)
.Case("sme2", HasSME2)
.Case("sme-f64f64", HasSMEF64F64)
.Case("sme-i16i64", HasSMEI16I64)
.Case("sme-fa64", HasSMEFA64)
Expand Down Expand Up @@ -812,6 +829,12 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasBFloat16 = true;
HasFullFP16 = true;
}
if (Feature == "+sme2") {
HasSME = true;
HasSME2 = true;
HasBFloat16 = true;
HasFullFP16 = true;
}
if (Feature == "+sme-f64f64") {
HasSME = true;
HasSMEF64F64 = true;
Expand Down Expand Up @@ -1174,6 +1197,8 @@ TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
}

const char *const AArch64TargetInfo::GCCRegNames[] = {
// clang-format off

// 32-bit Integer registers
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
"w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
Expand Down Expand Up @@ -1210,7 +1235,12 @@ const char *const AArch64TargetInfo::GCCRegNames[] = {

// SVE predicate-as-counter registers
"pn0", "pn1", "pn2", "pn3", "pn4", "pn5", "pn6", "pn7", "pn8",
"pn9", "pn10", "pn11", "pn12", "pn13", "pn14", "pn15"
"pn9", "pn10", "pn11", "pn12", "pn13", "pn14", "pn15",

// SME registers
"za", "zt0",

// clang-format on
};

ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool HasCCDP = false;
bool HasFRInt3264 = false;
bool HasSME = false;
bool HasSME2 = false;
bool HasSMEF64F64 = false;
bool HasSMEI16I64 = false;
bool HasSB = false;
Expand Down
8 changes: 2 additions & 6 deletions clang/lib/Basic/Targets/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
return true;
}

bool HasLeftParen = false;
if (S.consume_front("{"))
HasLeftParen = true;
bool HasLeftParen = S.consume_front("{");
if (S.empty())
return false;
if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
Expand All @@ -196,9 +194,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
Name = S.data() - 1;
return true;
}
bool HasLeftBracket = false;
if (S.consume_front("["))
HasLeftBracket = true;
bool HasLeftBracket = S.consume_front("[");
unsigned long long N;
if (S.empty() || consumeUnsignedInteger(S, 10, N))
return false;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ bool X86TargetInfo::initFeatureMap(
if (Feature.substr(1, 6) == "avx10.") {
if (Feature[0] == '+') {
HasAVX10 = true;
if (Feature.substr(Feature.size() - 3, 3) == "512")
if (StringRef(Feature).ends_with("512"))
HasAVX10_512 = true;
LastAVX10 = Feature;
} else if (HasAVX10 && Feature == "-avx10.1-256") {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: X86_32TargetInfo(Triple, Opts) {
LongDoubleWidth = 64;
DefaultAlignForAttributeAligned = 32;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-"
"f64:32-f128:32-n8:16:32-a:0:32-S32");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
LangOptions::FPModeKind::FPM_FastHonorPragmas);
Options.ApproxFuncFPMath = LangOpts.ApproxFunc;

Options.BBAddrMap = CodeGenOpts.BBAddrMap;
Options.BBSections =
llvm::StringSwitch<llvm::BasicBlockSection>(CodeGenOpts.BBSections)
.Case("all", llvm::BasicBlockSection::All)
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5710,6 +5710,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Value *HalfVal = Builder.CreateLoad(Address);
return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getFloatTy()));
}
case Builtin::BI__builtin_printf:
case Builtin::BIprintf:
if (getTarget().getTriple().isNVPTX() ||
getTarget().getTriple().isAMDGCN()) {
Expand Down Expand Up @@ -17756,9 +17757,9 @@ Value *EmitAMDGPUImplicitArgPtr(CodeGenFunction &CGF) {
// \p Index is 0, 1, and 2 for x, y, and z dimension, respectively.
/// Emit code based on Code Object ABI version.
/// COV_4 : Emit code to use dispatch ptr
/// COV_5 : Emit code to use implicitarg ptr
/// COV_5+ : Emit code to use implicitarg ptr
/// COV_NONE : Emit code to load a global variable "__oclc_ABI_version"
/// and use its value for COV_4 or COV_5 approach. It is used for
/// and use its value for COV_4 or COV_5+ approach. It is used for
/// compiling device libraries in an ABI-agnostic way.
///
/// Note: "__oclc_ABI_version" is supposed to be emitted and intialized by
Expand Down Expand Up @@ -17801,7 +17802,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) {
Address(Result, CGF.Int16Ty, CharUnits::fromQuantity(2)));
} else {
Value *GEP = nullptr;
if (Cov == CodeObjectVersionKind::COV_5) {
if (Cov >= CodeObjectVersionKind::COV_5) {
// Indexing the implicit kernarg segment.
GEP = CGF.Builder.CreateConstGEP1_32(
CGF.Int8Ty, EmitAMDGPUImplicitArgPtr(CGF), 12 + Index * 2);
Expand Down
40 changes: 37 additions & 3 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3216,6 +3216,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
}
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
llvm::TypeSize StructSize;
llvm::TypeSize PtrElementSize;
if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
PtrElementSize =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty));
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(StructSize == PtrElementSize &&
"Only allow non-fractional movement of structure with"
"homogeneous scalable vector type");

ArgVals.push_back(ParamValue::forDirect(AI));
break;
}
}

Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
Arg->getName());

Expand All @@ -3224,7 +3243,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,

// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
llvm::TypeSize StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
Expand Down Expand Up @@ -5287,6 +5305,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
break;
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
llvm::TypeSize SrcTypeSize;
llvm::TypeSize DstTypeSize;
if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) {
SrcTypeSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy);
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(SrcTypeSize == DstTypeSize &&
"Only allow non-fractional movement of structure with "
"homogeneous scalable vector type");

IRCallArgs[FirstIRArg] = I->getKnownRValue().getScalarVal();
break;
}
}

// FIXME: Avoid the conversion through memory if possible.
Address Src = Address::invalid();
if (!I->isAggregate()) {
Expand All @@ -5302,8 +5338,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,

// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
llvm::Type *SrcTy = Src.getElementType();
llvm::TypeSize SrcTypeSize =
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGGPUBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ RValue EmitDevicePrintfCallExpr(const CallExpr *E, CodeGenFunction *CGF,
llvm::Function *Decl, bool WithSizeArg) {
CodeGenModule &CGM = CGF->CGM;
CGBuilderTy &Builder = CGF->Builder;
assert(E->getBuiltinCallee() == Builtin::BIprintf);
assert(E->getBuiltinCallee() == Builtin::BIprintf ||
E->getBuiltinCallee() == Builtin::BI__builtin_printf);
assert(E->getNumArgs() >= 1); // printf always has at least one arg.

// Uses the same format as nvptx for the argument packing, but also passes
Expand Down
14 changes: 4 additions & 10 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,17 +1044,14 @@ void CodeGenModule::Release() {
llvm::MDString::get(VMContext, "ascii"));
}

llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
if ( Arch == llvm::Triple::arm
|| Arch == llvm::Triple::armeb
|| Arch == llvm::Triple::thumb
|| Arch == llvm::Triple::thumbeb) {
llvm::Triple T = Context.getTargetInfo().getTriple();
if (T.isARM() || T.isThumb()) {
// The minimum width of an enum in bytes
uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4;
getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
}

if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64) {
if (T.isRISCV()) {
StringRef ABIStr = Target.getABI();
llvm::LLVMContext &Ctx = TheModule.getContext();
getModule().addModuleFlag(llvm::Module::Error, "target-abi",
Expand Down Expand Up @@ -1127,10 +1124,7 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Override,
"tag-stack-memory-buildattr", 1);

if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::aarch64_be) {
if (T.isARM() || T.isThumb() || T.isAArch64()) {
if (LangOpts.BranchTargetEnforcement)
getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
1);
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ static llvm::cl::opt<bool>
llvm::cl::desc("Enable value profiling"),
llvm::cl::Hidden, llvm::cl::init(false));

extern llvm::cl::opt<bool> SystemHeadersCoverage;

using namespace clang;
using namespace CodeGen;

Expand Down Expand Up @@ -1022,7 +1024,7 @@ bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
// Don't map the functions in system headers.
const auto &SM = CGM.getContext().getSourceManager();
auto Loc = D->getBody()->getBeginLoc();
return SM.isInSystemHeader(Loc);
return !SystemHeadersCoverage && SM.isInSystemHeader(Loc);
}

void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static llvm::cl::opt<bool> EmptyLineCommentCoverage(
"disable it on test)"),
llvm::cl::init(true), llvm::cl::Hidden);

static llvm::cl::opt<bool> SystemHeadersCoverage(
llvm::cl::opt<bool> SystemHeadersCoverage(
"system-headers-coverage",
llvm::cl::desc("Enable collecting coverage from system headers"),
llvm::cl::init(false), llvm::cl::Hidden);
Expand Down Expand Up @@ -1812,8 +1812,10 @@ struct CounterCoverageMappingBuilder
assert(S->isConstexpr());

// evaluate constant condition...
const auto *E = cast<ConstantExpr>(S->getCond());
const bool isTrue = E->getResultAsAPSInt().getExtValue();
const bool isTrue =
S->getCond()
->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
.getBoolValue();

extendRegion(S);

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,9 +1347,10 @@ static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {

llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);

// Mark the function as nounwind readonly.
// Mark the function as nounwind willreturn readonly.
llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext());
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
llvm::AttributeList Attrs = llvm::AttributeList::get(
CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CodeGen/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,13 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}

return ABIArgInfo::getDirect();
ABIArgInfo Info = ABIArgInfo::getDirect();

// If it is tuple type, it can't be flattened.
if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)))
Info.setCanBeFlattened(!STy->containsHomogeneousScalableVectorTypes());

return Info;
}

if (const VectorType *VT = Ty->getAs<VectorType>())
Expand Down
19 changes: 10 additions & 9 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,15 +1443,16 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
const ToolChain &TC = getToolChain(
*UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));

if (TC.getTriple().isAndroid()) {
llvm::Triple Triple = TC.getTriple();
StringRef TripleVersionName = Triple.getEnvironmentVersionString();

if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "") {
Diags.Report(diag::err_drv_triple_version_invalid)
<< TripleVersionName << TC.getTripleString();
ContainsError = true;
}
// Check if the environment version is valid.
llvm::Triple Triple = TC.getTriple();
StringRef TripleVersionName = Triple.getEnvironmentVersionString();
StringRef TripleObjectFormat =
Triple.getObjectFormatTypeName(Triple.getObjectFormat());
if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "" &&
TripleVersionName != TripleObjectFormat) {
Diags.Report(diag::err_drv_triple_version_invalid)
<< TripleVersionName << TC.getTripleString();
ContainsError = true;
}

// Report warning when arm64EC option is overridden by specified target
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,12 @@ void AMDGPUToolChain::addClangTargetOptions(
}
}

void AMDGPUToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
// AMDGPU does not support atomic lib call. Treat atomic alignment
// warnings as errors.
CC1Args.push_back("-Werror=atomic-alignment");
}

StringRef
AMDGPUToolChain::getGPUArch(const llvm::opt::ArgList &DriverArgs) const {
return getProcessorFromTargetID(
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
/// Get GPU arch from -mcpu without checking.
StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;

/// Common warning options shared by AMDGPU HIP, OpenCL and OpenMP toolchains.
/// Language specific warning options should go to derived classes.
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
};

class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(

void AMDGPUOpenMPToolChain::addClangWarningOptions(
ArgStringList &CC1Args) const {
AMDGPUToolChain::addClangWarningOptions(CC1Args);
HostTC.addClangWarningOptions(CC1Args);
}

Expand Down
Loading