Compare commits

..

2 Commits

Author SHA1 Message Date
Tom Eccles
16662ce212 Check for loosely-strictured block instead of maintaining a flag 2025-08-21 15:46:19 +00:00
Tom Eccles
040a19d127 [flang][OpenMP] move omp end directive validation to semantics
The old parse tree errors quckly exploded to thousands of unhelpful
lines when there were multiple missing end directives (e.g. #90452).

Instead I've added a flag to the parse tree indicating when a missing
end directive needs to be diagnosed, and moved the error messages to
semantics (where they are a lot easier to control).

This has the disadvantage of not displaying the error if there were
other parse errors, but there is a precedent for this approach (e.g.
parsing atomic constructs).
2025-08-21 11:18:53 +00:00
817 changed files with 21057 additions and 75846 deletions

View File

@ -60,8 +60,7 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
-D LLDB_ENABLE_PYTHON=ON \
-D LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS=ON \
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-D CMAKE_EXE_LINKER_FLAGS="-no-pie"
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
start-group "ninja"

View File

@ -138,12 +138,6 @@
Dump function CFGs to graphviz format after each stage;enable '-print-loops'
for color-coded blocks
- `--dump-dot-func=<func1,func2,func3...>`
Dump function CFGs to graphviz format for specified functions only;
takes function name patterns (regex supported). Note: C++ function names
must be passed using their mangled names
- `--dump-linux-exceptions`
Dump Linux kernel exception table

View File

@ -15,12 +15,6 @@
#include "llvm/Support/CommandLine.h"
namespace llvm {
namespace bolt {
class BinaryFunction;
}
} // namespace llvm
namespace opts {
enum HeatmapModeKind {
@ -106,9 +100,6 @@ extern llvm::cl::opt<unsigned> Verbosity;
/// Return true if we should process all functions in the binary.
bool processAllFunctions();
/// Return true if we should dump dot graphs for the given function.
bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function);
enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;

View File

@ -52,7 +52,6 @@ namespace opts {
extern cl::opt<bool> PrintAll;
extern cl::opt<bool> PrintDynoStats;
extern cl::opt<bool> DumpDotAll;
extern bool shouldDumpDot(const bolt::BinaryFunction &Function);
extern cl::opt<std::string> AsmDump;
extern cl::opt<bolt::PLTCall::OptType> PLT;
extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
@ -341,7 +340,7 @@ Error BinaryFunctionPassManager::runPasses() {
Function.print(BC.outs(), Message);
if (opts::shouldDumpDot(Function))
if (opts::DumpDotAll)
Function.dumpGraphForPass(PassIdName);
}
}

View File

@ -115,35 +115,6 @@ cl::opt<bool> DumpDotAll(
"enable '-print-loops' for color-coded blocks"),
cl::Hidden, cl::cat(BoltCategory));
cl::list<std::string> DumpDotFunc(
"dump-dot-func", cl::CommaSeparated,
cl::desc(
"dump function CFGs to graphviz format for specified functions only;"
"takes function name patterns (regex supported)"),
cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));
bool shouldDumpDot(const bolt::BinaryFunction &Function) {
// If dump-dot-all is enabled, dump all functions
if (DumpDotAll)
return !Function.isIgnored();
// If no specific functions specified in dump-dot-func, don't dump any
if (DumpDotFunc.empty())
return false;
if (Function.isIgnored())
return false;
// Check if function matches any of the specified patterns
for (const std::string &Name : DumpDotFunc) {
if (Function.hasNameRegex(Name)) {
return true;
}
}
return false;
}
static cl::list<std::string>
ForceFunctionNames("funcs",
cl::CommaSeparated,
@ -3598,7 +3569,7 @@ void RewriteInstance::postProcessFunctions() {
if (opts::PrintAll || opts::PrintCFG)
Function.print(BC->outs(), "after building cfg");
if (opts::shouldDumpDot(Function))
if (opts::DumpDotAll)
Function.dumpGraphForPass("00_build-cfg");
if (opts::PrintLoopInfo) {

View File

@ -1,24 +0,0 @@
#include <iostream>
// Multiple functions to test selective dumping
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main_helper() {
std::cout << "Helper function" << std::endl;
return 42;
}
int main_secondary() { return add(5, 3); }
void other_function() { std::cout << "Other function" << std::endl; }
int main() {
int result = add(10, 20);
result = multiply(result, 2);
main_helper();
main_secondary();
other_function();
return result;
}

View File

@ -1,52 +0,0 @@
# Test the --dump-dot-func option with multiple functions
# (includes tests for both mangled/unmangled names)
RUN: %clang++ %p/Inputs/multi-func.cpp -o %t.exe -Wl,-q
# Test 1: --dump-dot-func with specific function name (mangled)
RUN: llvm-bolt %t.exe -o %t.bolt1 --dump-dot-func=_Z3addii -v=1 2>&1 | FileCheck %s --check-prefix=ADD
# Test 2: --dump-dot-func with regex pattern (main.*)
RUN: llvm-bolt %t.exe -o %t.bolt2 --dump-dot-func="main.*" -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-REGEX
# Test 3: --dump-dot-func with multiple specific functions (mangled names)
RUN: llvm-bolt %t.exe -o %t.bolt3 --dump-dot-func=_Z3addii,_Z8multiplyii -v=1 2>&1 | FileCheck %s --check-prefix=MULTI
# Test 4: No option specified should create no dot files
RUN: llvm-bolt %t.exe -o %t.bolt4 2>&1 | FileCheck %s --check-prefix=NONE
# Test 5: --dump-dot-func with non-existent function
RUN: llvm-bolt %t.exe -o %t.bolt5 --dump-dot-func=nonexistent -v=1 2>&1 | FileCheck %s --check-prefix=NONEXISTENT
# Test 6: Backward compatibility - --dump-dot-all should still work
RUN: llvm-bolt %t.exe -o %t.bolt6 --dump-dot-all -v=1 2>&1 | FileCheck %s --check-prefix=ALL
# Test 7: Test with unmangled function name (main function)
RUN: llvm-bolt %t.exe -o %t.bolt7 --dump-dot-func=main -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-UNMANGLED
# Check that specific functions are dumped
ADD: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
MAIN-REGEX-DAG: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
# Should be no dumping messages when no option is specified
NONE-NOT: BOLT-INFO: dumping CFG
# Should be no dumping messages for non-existent function
NONEXISTENT-NOT: BOLT-INFO: dumping CFG
ALL: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot

View File

@ -1575,10 +1575,6 @@ template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallSet<T, N>>;
template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallPtrSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallPtrSet<T, N>>;
/// Returns whether the sets mapped to the two elements in the map have at
/// least one element in common.
template <typename MapTy, typename ElemTy>
@ -1703,7 +1699,7 @@ public:
/// Implements the heuristic that marks two parameters related if the same
/// member is accessed (referred to) inside the current function's body.
class AccessedSameMemberOf {
ParamToSmallPtrSetMap<const Decl *> AccessedMembers;
ParamToSmallSetMap<const Decl *> AccessedMembers;
public:
void setup(const FunctionDecl *FD) {

View File

@ -15,12 +15,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
namespace {
// Determine if the result of an expression is "stored" in some way.
// It is true if the value is stored into a variable or used as initialization
// or passed to a function or constructor.
// For this use case compound assignments are not counted as a "store" (the 'E'
// expression should have pointer type).
static bool isExprValueStored(const Expr *E, ASTContext &C) {
bool isExprValueStored(const Expr *E, ASTContext &C) {
E = E->IgnoreParenCasts();
// Get first non-paren, non-cast parent.
ParentMapContext &PMap = C.getParentMapContext();
@ -47,8 +49,6 @@ static bool isExprValueStored(const Expr *E, ASTContext &C) {
return isa<CallExpr, CXXConstructExpr>(ParentE);
}
namespace {
AST_MATCHER_P(CXXTryStmt, hasHandlerFor,
ast_matchers::internal::Matcher<QualType>, InnerMatcher) {
for (unsigned NH = Node.getNumHandlers(), I = 0; I < NH; ++I) {

View File

@ -14,8 +14,10 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
namespace {
bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
// String literals surrounded by parentheses are assumed to be on purpose.
// i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] };
@ -56,8 +58,6 @@ static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
return false;
}
namespace {
AST_MATCHER_P(StringLiteral, isConcatenatedLiteral, unsigned,
MaxConcatenatedTokens) {
return Node.getNumConcatenated() > 1 &&

View File

@ -46,9 +46,7 @@ enum class ConversionKind {
ToLongDouble
};
} // namespace
static ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
return llvm::StringSwitch<ConversionKind>(FD->getName())
.Cases("atoi", "atol", ConversionKind::ToInt)
.Case("atoll", ConversionKind::ToLongInt)
@ -56,8 +54,8 @@ static ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
.Default(ConversionKind::None);
}
static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
// Scan the format string for the first problematic format specifier, then
// report that as the conversion type. This will miss additional conversion
// specifiers, but that is acceptable behavior.
@ -130,7 +128,7 @@ static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
return H.get();
}
static StringRef classifyConversionType(ConversionKind K) {
StringRef classifyConversionType(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -150,7 +148,7 @@ static StringRef classifyConversionType(ConversionKind K) {
llvm_unreachable("Unknown conversion kind");
}
static StringRef classifyReplacement(ConversionKind K) {
StringRef classifyReplacement(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -175,6 +173,7 @@ static StringRef classifyReplacement(ConversionKind K) {
}
llvm_unreachable("Unknown conversion kind");
}
} // unnamed namespace
void StrToNumCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("expr");

View File

@ -59,9 +59,7 @@ AST_MATCHER(FunctionDecl, isPlacementOverload) {
return true;
}
} // namespace
static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
switch (FD->getOverloadedOperator()) {
default:
break;
@ -77,7 +75,7 @@ static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
llvm_unreachable("Not an overloaded allocation operator");
}
static const char *getOperatorName(OverloadedOperatorKind K) {
const char *getOperatorName(OverloadedOperatorKind K) {
switch (K) {
default:
break;
@ -93,14 +91,13 @@ static const char *getOperatorName(OverloadedOperatorKind K) {
llvm_unreachable("Not an overloaded allocation operator");
}
static bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
return RHS->getOverloadedOperator() == getCorrespondingOverload(LHS);
}
static bool
hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
if (RD) {
// Check the methods in the given class and accessible to derived classes.
for (const auto *BMD : RD->methods())
@ -127,6 +124,8 @@ hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
return false;
}
} // anonymous namespace
void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) {
// Match all operator new and operator delete overloads (including the array
// forms). Do not match implicit operators, placement operators, or

View File

@ -395,12 +395,16 @@ void MacroToEnumCallbacks::Endif(SourceLocation Loc, SourceLocation IfLoc) {
--CurrentFile->ConditionScopes;
}
namespace {
template <size_t N>
static bool textEquals(const char (&Needle)[N], const char *HayStack) {
bool textEquals(const char (&Needle)[N], const char *HayStack) {
return StringRef{HayStack, N - 1} == Needle;
}
template <size_t N> static size_t len(const char (&)[N]) { return N - 1; }
template <size_t N> size_t len(const char (&)[N]) { return N - 1; }
} // namespace
void MacroToEnumCallbacks::PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) {

View File

@ -16,13 +16,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
static constexpr char ConstructorCall[] = "constructorCall";
static constexpr char ResetCall[] = "resetCall";
static constexpr char NewExpression[] = "newExpression";
namespace {
static std::string getNewExprName(const CXXNewExpr *NewExpr,
const SourceManager &SM,
const LangOptions &Lang) {
constexpr char ConstructorCall[] = "constructorCall";
constexpr char ResetCall[] = "resetCall";
constexpr char NewExpression[] = "newExpression";
std::string getNewExprName(const CXXNewExpr *NewExpr, const SourceManager &SM,
const LangOptions &Lang) {
StringRef WrittenName = Lexer::getSourceText(
CharSourceRange::getTokenRange(
NewExpr->getAllocatedTypeSourceInfo()->getTypeLoc().getSourceRange()),
@ -33,6 +34,8 @@ static std::string getNewExprName(const CXXNewExpr *NewExpr,
return WrittenName.str();
}
} // namespace
const char MakeSmartPtrCheck::PointerType[] = "pointerType";
MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,

View File

@ -19,7 +19,9 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
static bool containsEscapes(StringRef HayStack, StringRef Escapes) {
namespace {
bool containsEscapes(StringRef HayStack, StringRef Escapes) {
size_t BackSlash = HayStack.find('\\');
if (BackSlash == StringRef::npos)
return false;
@ -33,16 +35,16 @@ static bool containsEscapes(StringRef HayStack, StringRef Escapes) {
return true;
}
static bool isRawStringLiteral(StringRef Text) {
bool isRawStringLiteral(StringRef Text) {
// Already a raw string literal if R comes before ".
const size_t QuotePos = Text.find('"');
assert(QuotePos != StringRef::npos);
return (QuotePos > 0) && (Text[QuotePos - 1] == 'R');
}
static bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
// FIXME: Handle L"", u8"", u"" and U"" literals.
if (!Literal->isOrdinary())
return false;
@ -62,12 +64,14 @@ static bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
return containsEscapes(Text, R"('\"?x01)");
}
static bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
return Bytes.find(Delimiter.empty()
? std::string(R"lit()")lit")
: (")" + Delimiter + R"(")")) != StringRef::npos;
}
} // namespace
RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -29,13 +29,12 @@
using namespace clang::ast_matchers;
namespace clang::tidy::objc {
namespace {
static constexpr StringRef WeakText = "__weak";
static constexpr StringRef StrongText = "__strong";
static constexpr StringRef UnsafeUnretainedText = "__unsafe_unretained";
namespace {
/// Matches ObjCIvarRefExpr, DeclRefExpr, or MemberExpr that reference
/// Objective-C object (or block) variables or fields whose object lifetimes
/// are not __unsafe_unretained.
@ -50,8 +49,6 @@ AST_POLYMORPHIC_MATCHER(isObjCManagedLifetime,
QT.getQualifiers().getObjCLifetime() > Qualifiers::OCL_ExplicitNone;
}
} // namespace
static std::optional<FixItHint>
fixItHintReplacementForOwnershipString(StringRef Text, CharSourceRange Range,
StringRef Ownership) {
@ -96,6 +93,8 @@ fixItHintForVarDecl(const VarDecl *VD, const SourceManager &SM,
return FixItHint::CreateInsertion(Range.getBegin(), "__unsafe_unretained ");
}
} // namespace
void NSInvocationArgumentLifetimeCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
traverse(

View File

@ -27,14 +27,11 @@ enum NamingStyle {
CategoryProperty = 2,
};
} // namespace
/// For now we will only fix 'CamelCase' or 'abc_CamelCase' property to
/// 'camelCase' or 'abc_camelCase'. For other cases the users need to
/// come up with a proper name by their own.
/// FIXME: provide fix for snake_case to snakeCase
static FixItHint generateFixItHint(const ObjCPropertyDecl *Decl,
NamingStyle Style) {
FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
auto Name = Decl->getName();
auto NewName = Decl->getName().str();
size_t Index = 0;
@ -53,7 +50,7 @@ static FixItHint generateFixItHint(const ObjCPropertyDecl *Decl,
return {};
}
static std::string validPropertyNameRegex(bool UsedInMatcher) {
std::string validPropertyNameRegex(bool UsedInMatcher) {
// Allow any of these names:
// foo
// fooBar
@ -75,13 +72,13 @@ static std::string validPropertyNameRegex(bool UsedInMatcher) {
return StartMatcher + "([a-z]|[A-Z][A-Z0-9])[a-z0-9A-Z]*$";
}
static bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
auto RegexExp =
llvm::Regex("^[a-zA-Z][a-zA-Z0-9]*_[a-zA-Z0-9][a-zA-Z0-9_]+$");
return RegexExp.match(PropertyName);
}
static bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
size_t Start = PropertyName.find_first_of('_');
assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
auto Prefix = PropertyName.substr(0, Start);
@ -91,6 +88,7 @@ static bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
auto RegexExp = llvm::Regex(llvm::StringRef(validPropertyNameRegex(false)));
return RegexExp.match(PropertyName.substr(Start + 1));
}
} // namespace
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(objcPropertyDecl(

View File

@ -17,6 +17,7 @@
#include <optional>
namespace clang::tidy::performance {
namespace {
using namespace ::clang::ast_matchers;
using llvm::StringRef;
@ -29,8 +30,8 @@ static constexpr StringRef MethodDeclId = "methodDecl";
static constexpr StringRef FunctionDeclId = "functionDecl";
static constexpr StringRef OldVarDeclId = "oldVarDecl";
static void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
if (!Var.getType().isLocalConstQualified()) {
if (std::optional<FixItHint> Fix = utils::fixit::addQualifierToVarDecl(
@ -39,8 +40,8 @@ static void recordFixes(const VarDecl &Var, ASTContext &Context,
}
}
static std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
bool Invalid = false;
const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
if (Invalid) {
@ -50,8 +51,8 @@ static std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
return Loc.getLocWithOffset(TextAfter[Offset] == '\0' ? Offset : Offset + 1);
}
static void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
auto &SM = Context.getSourceManager();
// Attempt to remove trailing comments as well.
auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
@ -73,8 +74,6 @@ static void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
}
}
namespace {
AST_MATCHER_FUNCTION_P(StatementMatcher,
isRefReturningMethodCallWithConstOverloads,
std::vector<StringRef>, ExcludedContainerTypes) {
@ -131,8 +130,6 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst,
hasUnaryOperand(OldVarDeclRef)))));
}
} // namespace
// This checks that the variable itself is only used as const, and also makes
// sure that it does not reference another variable that could be modified in
// the BlockStmt. It does this by checking the following:
@ -183,13 +180,13 @@ static bool isInitializingVariableImmutable(
return false;
}
static bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
return allDeclRefExprs(Var, BlockStmt, Context).empty();
}
static const SubstTemplateTypeParmType *
getSubstitutedType(const QualType &Type, ASTContext &Context) {
const SubstTemplateTypeParmType *getSubstitutedType(const QualType &Type,
ASTContext &Context) {
auto Matches = match(
qualType(anyOf(substTemplateTypeParmType().bind("subst"),
hasDescendant(substTemplateTypeParmType().bind("subst")))),
@ -197,9 +194,9 @@ getSubstitutedType(const QualType &Type, ASTContext &Context) {
return selectFirst<SubstTemplateTypeParmType>("subst", Matches);
}
static bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
if (const SubstTemplateTypeParmType *VarTmplType =
getSubstitutedType(VarType, Context)) {
if (const SubstTemplateTypeParmType *InitializerTmplType =
@ -215,8 +212,8 @@ static bool differentReplacedTemplateParams(const QualType &VarType,
return false;
}
static QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
if (OldVar) {
return OldVar->getType();
}
@ -227,6 +224,8 @@ static QualType constructorArgumentType(const VarDecl *OldVar,
return MethodDecl->getReturnType();
}
} // namespace
UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -21,14 +21,16 @@ using namespace clang::ast_matchers;
namespace clang::tidy::performance {
static std::string paramNameOrIndex(StringRef Name, size_t Index) {
namespace {
std::string paramNameOrIndex(StringRef Name, size_t Index) {
return (Name.empty() ? llvm::Twine('#') + llvm::Twine(Index + 1)
: llvm::Twine('\'') + Name + llvm::Twine('\''))
.str();
}
static bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
auto Matches = match(
traverse(TK_AsIs,
decl(forEachDescendant(declRefExpr(
@ -39,6 +41,8 @@ static bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
return Matches.empty();
}
} // namespace
UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -122,15 +122,15 @@ AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
return !AllEnumeratorsArePowersOfTwo;
}
} // namespace
static std::string getName(const EnumDecl *Decl) {
std::string getName(const EnumDecl *Decl) {
if (!Decl->getDeclName())
return "<unnamed>";
return Decl->getQualifiedNameAsString();
}
} // namespace
EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -144,8 +144,6 @@ struct CognitiveComplexity final {
void account(SourceLocation Loc, unsigned short Nesting, Criteria C);
};
} // namespace
// All the possible messages that can be output. The choice of the message
// to use is based of the combination of the CognitiveComplexity::Criteria.
// It would be nice to have it in CognitiveComplexity struct, but then it is
@ -165,27 +163,23 @@ static const std::array<const StringRef, 4> Msgs = {{
}};
// Criteria is a bitset, thus a few helpers are needed.
static CognitiveComplexity::Criteria
operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) |
llvm::to_underlying(RHS));
}
static CognitiveComplexity::Criteria
operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) &
llvm::to_underlying(RHS));
}
static CognitiveComplexity::Criteria &
operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria &operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator|(LHS, RHS);
return LHS;
}
static CognitiveComplexity::Criteria &
operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria &operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator&(LHS, RHS);
return LHS;
}
@ -205,8 +199,6 @@ void CognitiveComplexity::account(SourceLocation Loc, unsigned short Nesting,
Total += Increase;
}
namespace {
class FunctionASTVisitor final
: public RecursiveASTVisitor<FunctionASTVisitor> {
using Base = RecursiveASTVisitor<FunctionASTVisitor>;

View File

@ -41,11 +41,9 @@ AST_MATCHER(Stmt, isNULLMacroExpansion) {
return isNULLMacroExpansion(&Node, Finder->getASTContext());
}
} // namespace
static StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
switch (CastExprKind) {
case CK_IntegralToBoolean:
return Type->isUnsignedIntegerType() ? "0u" : "0";
@ -64,15 +62,15 @@ static StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
}
}
static bool isUnaryLogicalNotOperator(const Stmt *Statement) {
bool isUnaryLogicalNotOperator(const Stmt *Statement) {
const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
}
static void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
const Stmt *Parent, ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast, const Stmt *Parent,
ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
// In case of expressions like (! integer), we should remove the redundant not
// operator and use inverted comparison (integer == 0).
bool InvertComparison =
@ -135,8 +133,8 @@ static void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
}
static StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
if (isNULLMacroExpansion(Expression, Context)) {
return "false";
}
@ -163,7 +161,7 @@ static StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
return {};
}
static bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
SourceRange PrefixRange(Loc.getLocWithOffset(-1), Loc);
StringRef SpaceBeforeStmtStr = Lexer::getSourceText(
CharSourceRange::getCharRange(PrefixRange), Context.getSourceManager(),
@ -175,10 +173,9 @@ static bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
return !AllowedCharacters.contains(SpaceBeforeStmtStr.back());
}
static void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context,
StringRef OtherType) {
void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context, StringRef OtherType) {
if (!Context.getLangOpts().CPlusPlus) {
Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(),
(Twine("(") + OtherType + ")").str());
@ -203,9 +200,8 @@ static void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
}
}
static StringRef
getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
// Prior to C++11, false literal could be implicitly converted to pointer.
if (!Context.getLangOpts().CPlusPlus11 &&
(DestType->isPointerType() || DestType->isMemberPointerType()) &&
@ -226,8 +222,8 @@ getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
return BoolLiteral->getValue() ? "1" : "0";
}
static bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
std::queue<const Stmt *> Q;
Q.push(Cast);
@ -255,6 +251,8 @@ static bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
return false;
}
} // anonymous namespace
ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -28,11 +28,8 @@ AST_MATCHER_P(QualType, hasUnqualifiedType,
enum class Qualifier { Const, Volatile, Restrict };
} // namespace
static std::optional<Token>
findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
std::optional<Token> findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
// Since either of the locs can be in a macro, use `makeFileCharRange` to be
// sure that we have a consistent `CharSourceRange`, located entirely in the
// source file.
@ -61,7 +58,7 @@ findQualToken(const VarDecl *Decl, Qualifier Qual,
*Result.SourceManager);
}
static std::optional<SourceRange>
std::optional<SourceRange>
getTypeSpecifierLocation(const VarDecl *Var,
const MatchFinder::MatchResult &Result) {
SourceRange TypeSpecifier(
@ -76,8 +73,8 @@ getTypeSpecifierLocation(const VarDecl *Var,
return TypeSpecifier;
}
static std::optional<SourceRange>
mergeReplacementRange(SourceRange &TypeSpecifier, const Token &ConstToken) {
std::optional<SourceRange> mergeReplacementRange(SourceRange &TypeSpecifier,
const Token &ConstToken) {
if (TypeSpecifier.getBegin().getLocWithOffset(-1) == ConstToken.getEndLoc()) {
TypeSpecifier.setBegin(ConstToken.getLocation());
return std::nullopt;
@ -89,19 +86,21 @@ mergeReplacementRange(SourceRange &TypeSpecifier, const Token &ConstToken) {
return SourceRange(ConstToken.getLocation(), ConstToken.getEndLoc());
}
static bool isPointerConst(QualType QType) {
bool isPointerConst(QualType QType) {
QualType Pointee = QType->getPointeeType();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
static bool isAutoPointerConst(QualType QType) {
bool isAutoPointerConst(QualType QType) {
QualType Pointee =
cast<AutoType>(QType->getPointeeType().getTypePtr())->desugar();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
} // namespace
QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -14,18 +14,19 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
static const char *const RedundantReturnDiag =
"redundant return statement at the end "
"of a function with a void return type";
static const char *const RedundantContinueDiag =
"redundant continue statement at the "
"end of loop statement";
namespace {
static bool isLocationInMacroExpansion(const SourceManager &SM,
SourceLocation Loc) {
const char *const RedundantReturnDiag = "redundant return statement at the end "
"of a function with a void return type";
const char *const RedundantContinueDiag = "redundant continue statement at the "
"end of loop statement";
bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) {
return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
}
} // namespace
void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
functionDecl(isDefinition(), returns(voidType()),

View File

@ -13,14 +13,16 @@
namespace clang::tidy::utils::type_traits {
static bool classHasTrivialCopyAndDestroy(QualType Type) {
namespace {
bool classHasTrivialCopyAndDestroy(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
return Record && Record->hasDefinition() &&
!Record->hasNonTrivialCopyConstructor() &&
!Record->hasNonTrivialDestructor();
}
static bool hasDeletedCopyConstructor(QualType Type) {
bool hasDeletedCopyConstructor(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
if (!Record || !Record->hasDefinition())
return false;
@ -31,6 +33,8 @@ static bool hasDeletedCopyConstructor(QualType Type) {
return false;
}
} // namespace
std::optional<bool> isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
if (Type->isDependentType() || Type->isIncompleteType())

View File

@ -22,6 +22,10 @@ FeatureModule::Facilities &FeatureModule::facilities() {
return *Fac;
}
void FeatureModuleSet::add(std::unique_ptr<FeatureModule> M) {
Modules.push_back(std::move(M));
}
bool FeatureModuleSet::addImpl(void *Key, std::unique_ptr<FeatureModule> M,
const char *Source) {
if (!Map.try_emplace(Key, M.get()).second) {
@ -35,3 +39,5 @@ bool FeatureModuleSet::addImpl(void *Key, std::unique_ptr<FeatureModule> M,
} // namespace clangd
} // namespace clang
LLVM_INSTANTIATE_REGISTRY(clang::clangd::FeatureModuleRegistry)

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
#include <memory>
#include <optional>
#include <type_traits>
@ -143,9 +144,14 @@ private:
/// A FeatureModuleSet is a collection of feature modules installed in clangd.
///
/// Modules can be looked up by type, or used via the FeatureModule interface.
/// This allows individual modules to expose a public API.
/// For this reason, there can be only one feature module of each type.
/// Modules added with explicit type specification can be looked up by type, or
/// used via the FeatureModule interface. This allows individual modules to
/// expose a public API. For this reason, there can be only one feature module
/// of each type.
///
/// Modules added using a base class pointer can be used only via the
/// FeatureModule interface and can't be looked up by type, thus custom public
/// API (if provided by the module) can't be used.
///
/// The set owns the modules. It is itself owned by main, not ClangdServer.
class FeatureModuleSet {
@ -172,6 +178,7 @@ public:
const_iterator begin() const { return const_iterator(Modules.begin()); }
const_iterator end() const { return const_iterator(Modules.end()); }
void add(std::unique_ptr<FeatureModule> M);
template <typename Mod> bool add(std::unique_ptr<Mod> M) {
return addImpl(&ID<Mod>::Key, std::move(M), LLVM_PRETTY_FUNCTION);
}
@ -185,6 +192,8 @@ public:
template <typename Mod> int FeatureModuleSet::ID<Mod>::Key;
using FeatureModuleRegistry = llvm::Registry<FeatureModule>;
} // namespace clangd
} // namespace clang
#endif

View File

@ -1017,6 +1017,14 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
: static_cast<int>(ErrorResultCode::CheckFailed);
}
FeatureModuleSet ModuleSet;
for (FeatureModuleRegistry::entry E : FeatureModuleRegistry::entries()) {
vlog("Adding feature module '{0}' ({1})", E.getName(), E.getDesc());
ModuleSet.add(E.instantiate());
}
if (ModuleSet.begin() != ModuleSet.end())
Opts.FeatureModules = &ModuleSet;
// Initialize and run ClangdLSPServer.
// Change stdin to binary to not lose \r\n on windows.
llvm::sys::ChangeStdinToBinary();

View File

@ -215,8 +215,7 @@ Changes in existing checks
- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check by ignoring
declarations in system headers. The documentation is also improved to
differentiate the general options from the specific ones.
declarations in system headers.
- Improved :doc:`readability-qualified-auto
<clang-tidy/checks/readability/qualified-auto>` check by adding the option

View File

@ -43,21 +43,14 @@ The options and their corresponding values are:
- ``LowerCase`` - example: ``int i_Variable``
- ``CamelCase`` - example: ``int IVariable``
Options summary
---------------
Options
-------
The available options are summarized below:
**General options**
- :option:`AggressiveDependentMemberLookup`
- :option:`CheckAnonFieldInParent`
- :option:`GetConfigPerFile`
- :option:`IgnoreMainLikeFunctions`
**Specific options**
The following options are described below:
- :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, :option:`AbstractClassHungarianPrefix`
- :option:`AggressiveDependentMemberLookup`
- :option:`CheckAnonFieldInParent`
- :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`, :option:`ClassIgnoredRegexp`, :option:`ClassHungarianPrefix`
- :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, :option:`ClassConstantSuffix`, :option:`ClassConstantIgnoredRegexp`, :option:`ClassConstantHungarianPrefix`
- :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, :option:`ClassMemberSuffix`, :option:`ClassMemberIgnoredRegexp`, :option:`ClassMemberHungarianPrefix`
@ -73,11 +66,13 @@ The available options are summarized below:
- :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`, :option:`EnumIgnoredRegexp`
- :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, :option:`EnumConstantSuffix`, :option:`EnumConstantIgnoredRegexp`, :option:`EnumConstantHungarianPrefix`
- :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`, :option:`FunctionIgnoredRegexp`
- :option:`GetConfigPerFile`
- :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, :option:`GlobalConstantSuffix`, :option:`GlobalConstantIgnoredRegexp`, :option:`GlobalConstantHungarianPrefix`
- :option:`GlobalConstantPointerCase`, :option:`GlobalConstantPointerPrefix`, :option:`GlobalConstantPointerSuffix`, :option:`GlobalConstantPointerIgnoredRegexp`, :option:`GlobalConstantPointerHungarianPrefix`
- :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, :option:`GlobalFunctionSuffix`, :option:`GlobalFunctionIgnoredRegexp`
- :option:`GlobalPointerCase`, :option:`GlobalPointerPrefix`, :option:`GlobalPointerSuffix`, :option:`GlobalPointerIgnoredRegexp`, :option:`GlobalPointerHungarianPrefix`
- :option:`GlobalVariableCase`, :option:`GlobalVariablePrefix`, :option:`GlobalVariableSuffix`, :option:`GlobalVariableIgnoredRegexp`, :option:`GlobalVariableHungarianPrefix`
- :option:`IgnoreMainLikeFunctions`
- :option:`InlineNamespaceCase`, :option:`InlineNamespacePrefix`, :option:`InlineNamespaceSuffix`, :option:`InlineNamespaceIgnoredRegexp`
- :option:`LocalConstantCase`, :option:`LocalConstantPrefix`, :option:`LocalConstantSuffix`, :option:`LocalConstantIgnoredRegexp`, :option:`LocalConstantHungarianPrefix`
- :option:`LocalConstantPointerCase`, :option:`LocalConstantPointerPrefix`, :option:`LocalConstantPointerSuffix`, :option:`LocalConstantPointerIgnoredRegexp`, :option:`LocalConstantPointerHungarianPrefix`
@ -110,12 +105,6 @@ The available options are summarized below:
- :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`, :option:`VariableIgnoredRegexp`, :option:`VariableHungarianPrefix`
- :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, :option:`VirtualMethodSuffix`, :option:`VirtualMethodIgnoredRegexp`
Options description
-------------------
A detailed description of each option is presented below:
.. option:: AbstractClassCase
When defined, the check will ensure abstract class names conform to the

View File

@ -9,14 +9,14 @@ Introduction
============
Coroutines in C++ were introduced in C++20, and the user experience for
debugging them can still be challenging. This document guides you on how to most
debugging them can still be challenging. This document guides you how to most
efficiently debug coroutines and how to navigate existing shortcomings in
debuggers and compilers.
Coroutines are generally used either as generators or for asynchronous
programming. In this document, we will discuss both use cases. Even if you are
using coroutines for asynchronous programming, you should still read the
generators section, as it introduces foundational debugging techniques also
generators section, as it will introduce foundational debugging techniques also
applicable to the debugging of asynchronous programs.
Both compilers (clang, gcc, ...) and debuggers (lldb, gdb, ...) are
@ -34,15 +34,15 @@ scripting. This guide comes with a basic GDB script for coroutine debugging.
This guide will first showcase the more polished, bleeding-edge experience, but
will also show you how to debug coroutines with older toolchains. In general,
the older your toolchain, the deeper you will have to dive into the
implementation details of coroutines (such as their ABI). The further down you go in
this document, the more low-level, technical the content will become. If
implementation details of coroutines (such as their ABI). The further down in
this document you go, the more low-level, technical the content will become. If
you are on an up-to-date toolchain, you will hopefully be able to stop reading
earlier.
Debugging generators
====================
One of the two major use cases for coroutines in C++ is generators, i.e.,
One of the two major use cases for coroutines in C++ are generators, i.e.,
functions which can produce values via ``co_yield``. Values are produced
lazily, on-demand. For this purpose, every time a new value is requested, the
coroutine gets resumed. As soon as it reaches a ``co_yield`` and thereby
@ -141,7 +141,7 @@ a regular function.
Note the two additional variables ``__promise`` and ``__coro_frame``. Those
show the internal state of the coroutine. They are not relevant for our
generator example but will be relevant for asynchronous programming described
generator example, but will be relevant for asynchronous programming described
in the next section.
Stepping out of a coroutine
@ -174,7 +174,7 @@ Inspecting a suspended coroutine
--------------------------------
The ``print10Elements`` function receives an opaque ``generator`` type. Let's
assume we are suspended at the ``++gen;`` line and want to inspect the
assume we are suspended at the ``++gen;`` line, and want to inspect the
generator and its internal state.
To do so, we can simply look into the ``gen.hdl`` variable. LLDB comes with a
@ -188,7 +188,7 @@ We can see two function pointers ``resume`` and ``destroy``. These pointers
point to the resume / destroy functions. By inspecting those function pointers,
we can see that our ``generator`` is actually backed by our ``fibonacci``
coroutine. When using VS Code + lldb-dap, you can Cmd+Click on the function
address (``0x555...`` in the screenshot) to jump directly to the function
address (``0x555...`` in the screenshot) to directly jump to the function
definition backing your coroutine handle.
Next, we see the ``promise``. In our case, this reveals the current value of
@ -247,12 +247,12 @@ the line number of the current suspension point in the promise:
};
This stores the return address of ``await_suspend`` within the promise.
Thereby, we can read it back from the promise of a suspended coroutine and map
Thereby, we can read it back from the promise of a suspended coroutine, and map
it to an exact source code location. For a complete example, see the ``task``
type used below for asynchronous programming.
Alternatively, we can modify the C++ code to store the line number in the
promise type. We can use ``std::source_location`` to get the line number of
promise type. We can use a ``std::source_location`` to get the line number of
the await and store it inside the ``promise_type``. In the debugger, we can
then read the line number from the promise of the suspended coroutine.
@ -270,7 +270,7 @@ then read the line number from the promise of the suspended coroutine.
};
The downside of both approaches is that they come at the price of additional
runtime cost. In particular, the second approach increases binary size, since it
runtime cost. In particular the second approach increases binary size, since it
requires additional ``std::source_location`` objects, and those source
locations are not stripped by split-dwarf. Whether the first approach is worth
the additional runtime cost is a trade-off you need to make yourself.
@ -285,7 +285,7 @@ provide custom debugging support, so in addition to this guide, you might want
to check out their documentation.
When using coroutines for asynchronous programming, your library usually
provides you with some ``task`` type. This type usually looks similar to this:
provides you some ``task`` type. This type usually looks similar to this:
.. code-block:: c++
@ -479,7 +479,7 @@ One such solution is to store the list of in-flight coroutines in a collection:
};
With this in place, it is possible to inspect ``inflight_coroutines`` from the
debugger and rely on LLDB's ``std::coroutine_handle`` pretty-printer to
debugger, and rely on LLDB's ``std::coroutine_handle`` pretty-printer to
inspect the coroutines.
This technique will track *all* coroutines, also the ones which are currently
@ -498,8 +498,8 @@ LLDB before 21.0 did not yet show the ``__coro_frame`` inside
``coroutine_handle``. To inspect the coroutine frame, you had to use the
approach described in the :ref:`devirtualization` section.
LLDB before 18.0 hid the ``__promise`` and ``__coro_frame``
variables by default. The variables are still present, but they need to be
LLDB before 18.0 was hiding the ``__promise`` and ``__coro_frame``
variable by default. The variables are still present, but they need to be
explicitly added to the "watch" pane in VS Code or requested via
``print __promise`` and ``print __coro_frame`` from the debugger console.
@ -511,9 +511,9 @@ section.
Toolchain Implementation Details
================================
This section covers the ABI as well as additional compiler-specific behavior.
This section covers the ABI, as well as additional compiler-specific behavior.
The ABI is followed by all compilers, on all major systems, including Windows,
Linux, and macOS. Different compilers emit different debug information, though.
Linux and macOS. Different compilers emit different debug information, though.
Ramp, resume and destroy functions
----------------------------------
@ -595,7 +595,7 @@ functions as their first two members. As such, we can read the function
pointers from the coroutine frame and then obtain the function's name from its
address.
The promise is guaranteed to be at a 16-byte offset from the coroutine frame.
The promise is guaranteed to be at a 16 byte offset from the coroutine frame.
If we have a coroutine handle at address 0x416eb0, we can hence reinterpret-cast
the promise as follows:
@ -607,8 +607,8 @@ Implementation in clang / LLVM
------------------------------
The C++ Coroutines feature in the Clang compiler is implemented in two parts of
the compiler. Semantic analysis is performed in Clang, and coroutine
construction and optimization take place in the LLVM middle-end.
the compiler. Semantic analysis is performed in Clang, and Coroutine
construction and optimization takes place in the LLVM middle-end.
For each coroutine function, the frontend generates a single corresponding
LLVM-IR function. This function uses special ``llvm.coro.suspend`` intrinsics
@ -622,7 +622,7 @@ points into the coroutine frame. Most of the heavy lifting to preserve debugging
information is done in this pass. This pass needs to rewrite all variable
locations to point into the coroutine frame.
Afterwards, a couple of additional optimizations are applied before code
Afterwards, a couple of additional optimizations are applied, before code
gets emitted, but none of them are really interesting regarding debugging
information.
@ -636,8 +636,8 @@ However, this is not possible for coroutine frames because the frames are
constructed in the LLVM middle-end.
To mitigate this problem, the LLVM middle end attempts to generate some debug
information, which is unfortunately incomplete, since much of the
language-specific information is missing in the middle end.
information, which is unfortunately incomplete, since much of the language
specific information is missing in the middle end.
.. _devirtualization:
@ -655,7 +655,7 @@ There are two possible approaches to do so:
We can lookup their types and thereby get the types of promise
and coroutine frame.
In gdb, one can use the following approach to devirtualize a coroutine type,
In gdb, one can use the following approach to devirtualize coroutine type,
assuming we have a ``std::coroutine_handle`` is at address 0x418eb0:
::
@ -679,7 +679,7 @@ LLDB comes with devirtualization support out of the box, as part of the
pretty-printer for ``std::coroutine_handle``. Internally, this pretty-printer
uses the second approach. We look up the types in the destroy function and not
the resume function because the resume function pointer will be set to a
``nullptr`` as soon as a coroutine reaches its final suspension point. If we used
nullptr as soon as a coroutine reaches its final suspension point. If we used
the resume function, devirtualization would hence fail for all coroutines that
have reached their final suspension point.
@ -687,10 +687,10 @@ Interpreting the coroutine frame in optimized builds
----------------------------------------------------
The ``__coro_frame`` variable usually refers to the coroutine frame of an
*in-flight* coroutine. This means the coroutine is currently executing.
*in-flight* coroutine. This means, the coroutine is currently executing.
However, the compiler only guarantees the coroutine frame to be in a consistent
state while the coroutine is suspended. As such, the variables inside the
``__coro_frame`` variable might be outdated, particularly when optimizations
``__coro_frame`` variable might be outdated, in particular when optimizations
are enabled.
Furthermore, when optimizations are enabled, the compiler will layout the
@ -731,7 +731,7 @@ despite ``a`` being frequently incremented.
While this might be surprising, this is a result of the optimizer recognizing
that it can eliminate most of the load/store operations.
The above code is optimized to the equivalent of:
The above code gets optimized to the equivalent of:
.. code-block:: c++
@ -1180,5 +1180,5 @@ The authors of the Folly libraries wrote a blog post series on how they debug co
* `Async stack traces in folly: Improving debugging in the developer lifecycle <https://developers.facebook.com/blog/post/2021/10/21/async-stack-traces-folly-improving-debugging-developer-lifecycle/>`_
Besides some topics also covered here (stack traces from the debugger), Folly's blog post series also covers
additional topics, such as capturing async stack traces in performance profiles via eBPF filters
more additional topics, such as capturing async stack traces in performance profiles via eBPF filters
and printing async stack traces on crashes.

View File

@ -1763,7 +1763,6 @@ Hexadecimal floating constants (N308) C
Compound literals (N716) C99 C89, C++
``//`` comments (N644) C99 C89
Mixed declarations and code (N740) C99 C89
init-statement in for (N740) C99 C89
Variadic macros (N707) C99 C89
Empty macro arguments (N570) C99 C89
Trailing comma in enum declaration C99 C89

View File

@ -37,22 +37,6 @@ latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
Potentially Breaking Changes
============================
- Clang will now emit a warning if the auto-detected GCC installation
directory (i.e. the one with the largest version number) does not
contain libstdc++ include directories although a "complete" GCC
installation directory containing the include directories is
available. It is planned to change the auto-detection to prefer the
"complete" directory in the future. The warning will disappear if
the libstdc++ include directories are either installed or removed
for all GCC installation directories considered by the
auto-detection; see the output of ``clang -v`` for a list of those
directories. If the GCC installations cannot be modified and
maintaining the current choice of the auto-detection is desired, the
GCC installation directory can be selected explicitly using the
``--gcc-install-dir`` command line argument. This will silence the
warning. It can also be disabled using the
``-Wno-gcc-install-dir-libstdcxx`` command line flag.
C/C++ Language Potentially Breaking Changes
-------------------------------------------
@ -245,7 +229,6 @@ Bug Fixes in This Version
cast chain. (#GH149967).
- Fixed a crash with incompatible pointer to integer conversions in designated
initializers involving string literals. (#GH154046)
- Fixed scope of typedefs present inside a template class. (#GH91451)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -309,13 +292,6 @@ NVPTX Support
X86 Support
^^^^^^^^^^^
- More SSE, AVX and AVX512 intrinsics, including initializers and general
arithmetic can now be used in C++ constant expressions.
- Some SSE, AVX and AVX512 intrinsics have been converted to wrap
generic __builtin intrinsics.
- NOTE: Please avoid use of the __builtin_ia32_* intrinsics - these are not
guaranteed to exist in future releases, or match behaviour with previous
releases of clang or other compilers.
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -23,20 +23,20 @@
#include "clang/Basic/DiagnosticInstallAPI.h"
#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/DiagnosticRefactoring.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/DiagnosticSerialization.h"
#include "clang/Basic/DiagnosticRefactoring.h"
namespace clang {
template <size_t SizeOfStr, typename FieldType> class StringSizerHelper {
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper {
static_assert(SizeOfStr <= FieldType(~0U), "Field too small!");
public:
enum { Size = SizeOfStr };
};
} // end namespace clang
#define STR_SIZE(str, fieldTy) \
clang::StringSizerHelper<sizeof(str) - 1, fieldTy>::Size
#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \
fieldTy>::Size
#endif

View File

@ -627,23 +627,11 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def pmulhuw256 : X86Builtin<"_Vector<16, unsigned short>(_Vector<16, unsigned short>, _Vector<16, unsigned short>)">;
def pmulhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
def psllv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psrav8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psrlv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psllv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
def psrlv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def psllv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psrav4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psrlv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psllv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
def psrlv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmulhuw256 : X86Builtin<"_Vector<16, unsigned short>(_Vector<16, unsigned short>, _Vector<16, unsigned short>)">;
def pmulhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
}
let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<256>] in {
@ -666,6 +654,46 @@ let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<128>] in {
def maskstoreq : X86Builtin<"void(_Vector<2, long long int *>, _Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psllv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psllv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psllv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psllv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrav8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrav4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrlv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrlv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrlv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrlv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<128>] in {
def gatherd_pd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, double const *, _Vector<4, int>, _Vector<2, double>, _Constant char)">;
}

View File

@ -885,9 +885,4 @@ def warn_drv_openacc_without_cir
: Warning<"OpenACC directives will result in no runtime behavior; use "
"-fclangir to enable runtime effect">,
InGroup<SourceUsesOpenACC>;
def warn_drv_gcc_install_dir_libstdcxx : Warning<
"future releases of the clang compiler will prefer GCC installations "
"containing libstdc++ include directories; '%0' would be chosen over '%1'">,
InGroup<DiagGroup<"gcc-install-dir-libstdcxx">>;
}

View File

@ -23,78 +23,76 @@
#include <vector>
namespace clang {
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;
// Import the diagnostic enums themselves.
namespace diag {
enum class Group;
// Import the diagnostic enums themselves.
namespace diag {
enum class Group;
// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
};
// Start position for diagnostics.
// clang-format off
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
};
// clang-format on
// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
};
// Start position for diagnostics.
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
};
class CustomDiagInfo;
class CustomDiagInfo;
/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};
/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
} // end namespace clang
// This has to be included *after* the DIAG_START_ enums above are defined.
@ -175,8 +173,7 @@ public:
/// Used for handling and querying diagnostic IDs.
///
/// Can be used and shared by multiple Diagnostics for multiple translation
/// units.
/// Can be used and shared by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
/// The level of the diagnostic, after it has been through mapping.
@ -501,6 +498,6 @@ private:
friend class DiagnosticsEngine;
};
} // end namespace clang
} // end namespace clang
#endif

View File

@ -50,45 +50,6 @@ class CIR_UnitAttr<string name, string attrMnemonic, list<Trait> traits = []>
let isOptional = 1;
}
//===----------------------------------------------------------------------===//
// SourceLanguageAttr
//===----------------------------------------------------------------------===//
// TODO: Add cases for other languages that Clang supports.
def CIR_SourceLanguage : CIR_I32EnumAttr<"SourceLanguage", "source language", [
I32EnumAttrCase<"C", 1, "c">,
I32EnumAttrCase<"CXX", 2, "cxx">
]> {
// The enum attr class is defined in `CIR_SourceLanguageAttr` below,
// so that it can define extra class methods.
let genSpecializedAttr = 0;
}
def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> {
let summary = "Module source language";
let description = [{
Represents the source language used to generate the module.
Example:
```
// Module compiled from C.
module attributes {cir.lang = cir.lang<c>} {}
// Module compiled from C++.
module attributes {cir.lang = cir.lang<cxx>} {}
```
Module source language attribute name is `cir.lang` is defined by
`getSourceLanguageAttrName` method in CIRDialect class.
}];
let extraClassDeclaration = [{
bool isC() const { return getValue() == SourceLanguage::C; }
bool isCXX() const { return getValue() == SourceLanguage::CXX; }
}];
}
//===----------------------------------------------------------------------===//
// OptInfoAttr
//===----------------------------------------------------------------------===//
@ -535,72 +496,6 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
}];
}
//===----------------------------------------------------------------------===//
// VTableAttr
//===----------------------------------------------------------------------===//
def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
let summary = "Represents a C++ vtable";
let description = [{
Wraps a #cir.const_record containing one or more vtable arrays.
In most cases, the anonymous record type wrapped by this attribute will
contain a single array corresponding to the vtable for one class. However,
in the case of multiple inheritence, the anonymous structure may contain
multiple arrays, each of which is a vtable.
Example 1 (single vtable):
```mlir
cir.global linkonce_odr @_ZTV6Mother =
#cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI6Mother> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother9MotherFooEv> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>
}> : !rec_anon_struct1
```
Example 2 (multiple vtables):
```mlir
cir.global linkonce_odr @_ZTV5Child =
#cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN5Child9MotherFooEv> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>,
#cir.const_array<[
#cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Father9FatherFooEv> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 3>
}> : !rec_anon_struct2
```
}];
// `data` is a const record with one element, containing an array of
// vtable information.
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
"mlir::ArrayAttr":$data
);
let builders = [
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
"mlir::ArrayAttr":$data), [{
return $_get(type.getContext(), type, data);
}]>
];
let genVerifyDecl = 1;
let assemblyFormat = [{
`<` custom<RecordMembers>($data) `>`
}];
}
//===----------------------------------------------------------------------===//
// ConstComplexAttr
//===----------------------------------------------------------------------===//

View File

@ -35,7 +35,6 @@ def CIR_Dialect : Dialect {
let hasConstantMaterializer = 1;
let extraClassDeclaration = [{
static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; }
static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
static llvm::StringRef getCalleeAttrName() { return "callee"; }

View File

@ -26,7 +26,6 @@ std::unique_ptr<Pass> createCIRSimplifyPass();
std::unique_ptr<Pass> createHoistAllocasPass();
std::unique_ptr<Pass> createLoweringPreparePass();
std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createGotoSolverPass();
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);

View File

@ -72,16 +72,6 @@ def CIRFlattenCFG : Pass<"cir-flatten-cfg"> {
let dependentDialects = ["cir::CIRDialect"];
}
def GotoSolver : Pass<"cir-goto-solver"> {
let summary = "Replaces goto operations with branches";
let description = [{
This pass transforms CIR and replaces goto-s with branch
operations to the proper blocks.
}];
let constructor = "mlir::createGotoSolverPass()";
let dependentDialects = ["cir::CIRDialect"];
}
def LoweringPrepare : Pass<"cir-lowering-prepare"> {
let summary = "Lower to more fine-grained CIR operations before lowering to "
"other dialects";

View File

@ -264,7 +264,6 @@ struct MissingFeatures {
static bool setNonGC() { return false; }
static bool setObjCGCLValueClass() { return false; }
static bool setTargetAttributes() { return false; }
static bool sourceLanguageCases() { return false; }
static bool stackBase() { return false; }
static bool stackSaveOp() { return false; }
static bool targetCIRGenInfoArch() { return false; }

View File

@ -32,7 +32,6 @@
namespace llvm {
class AttrBuilder;
class Constant;
class ConstantInt;
class Function;
class FunctionType;
class Type;
@ -127,12 +126,6 @@ uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD);
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
QualType FunctionType);
/// Return a signed constant pointer.
llvm::Constant *getConstantSignedPointer(CodeGenModule &CGM,
llvm::Constant *Pointer, unsigned Key,
llvm::Constant *StorageAddress,
llvm::ConstantInt *OtherDiscriminator);
/// Given the language and code-generation options that Clang was configured
/// with, set the default LLVM IR attributes for a function definition.
/// The attributes set here are mostly global target-configuration and

View File

@ -9468,12 +9468,8 @@ def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group<dxc_Group>,
def fspv_extension_EQ
: Joined<["-"], "fspv-extension=">,
Group<dxc_Group>,
HelpText<
"Specify the available SPIR-V extensions. If this option is not "
"specified, then all extensions are available. If KHR is specified, "
"then all KHR extensions will be available. If DXC is specifided, "
"then all extensions implemented by the DirectX Shader compiler will "
"be available. This option is useful for moving from DXC to Clang.">;
HelpText<"Specify the available SPIR-V extensions. If this option is not "
"specified, then all extensions are available.">;
def fvk_use_dx_layout
: DXCFlag<"fvk-use-dx-layout">,
HelpText<"Use DirectX memory layout for Vulkan resources.">;

View File

@ -224,6 +224,9 @@ protected:
static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
@ -243,9 +246,6 @@ protected:
///@}
public:
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
virtual ~ToolChain();
// Accessors

View File

@ -1640,9 +1640,6 @@ bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
const Pointer &Field = Ptr.atField(I);
Field.deref<T>() = Value;
Field.initialize();
@ -1655,9 +1652,6 @@ bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
const Pointer &Field = Ptr.atField(I);
Field.deref<T>() = Value;
Field.activate();
@ -1669,13 +1663,7 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
const Pointer &Field = Ptr.atField(F->Offset);
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
@ -1701,13 +1689,7 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
const Pointer &Field = Ptr.atField(F->Offset);
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
@ -1806,8 +1788,6 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
return false;
if (!Ptr.isBlockPointer()) {
if (!Ptr.isIntegralPointer())
return false;
S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
return true;
}
@ -1829,8 +1809,6 @@ inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off,
return false;
if (!Ptr.isBlockPointer()) {
if (!Ptr.isIntegralPointer())
return false;
S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
return true;
}
@ -2459,17 +2437,9 @@ inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Current->getLocalPointer(Local.Offset);
if (Ptr.getLifetime() == Lifetime::Ended) {
// Try to use the declaration for better diagnostics
if (const Decl *D = Ptr.getDeclDesc()->asDecl()) {
auto *ND = cast<NamedDecl>(D);
S.FFDiag(ND->getLocation(),
diag::note_constexpr_destroy_out_of_lifetime)
<< ND->getNameAsString();
} else {
S.FFDiag(Ptr.getDeclDesc()->getLocation(),
diag::note_constexpr_destroy_out_of_lifetime)
<< Ptr.toDiagnosticString(S.getASTContext());
}
auto *D = cast<NamedDecl>(Ptr.getFieldDesc()->asDecl());
S.FFDiag(D->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
<< D->getNameAsString();
return false;
}
}

View File

@ -205,8 +205,6 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (A.isDummy() || B.isDummy())
return false;
if (!A.isBlockPointer() || !B.isBlockPointer())
return false;
bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
ID == Builtin::BI__builtin_wcscmp ||
@ -214,10 +212,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
assert(A.getFieldDesc()->isPrimitiveArray());
assert(B.getFieldDesc()->isPrimitiveArray());
// Different element types shouldn't happen, but with casts they can.
if (!S.getASTContext().hasSameUnqualifiedType(getElemType(A), getElemType(B)))
return false;
assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
PrimType ElemT = *S.getContext().classify(getElemType(A));
auto returnResult = [&](int V) -> bool {
@ -2688,10 +2683,9 @@ static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC,
const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
PrimType ElemT = *S.getContext().classify(VT->getElementType());
unsigned SourceLen = VT->getNumElements();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen / 2);
PrimType DstElemT = *S.getContext().classify(
Call->getType()->castAs<VectorType>()->getElementType());
unsigned DstElem = 0;
for (unsigned I = 0; I != SourceLen; I += 2) {
APSInt Elem1;
APSInt Elem2;
@ -2705,19 +2699,16 @@ static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC,
case clang::X86::BI__builtin_ia32_pmuludq128:
case clang::X86::BI__builtin_ia32_pmuludq256:
case clang::X86::BI__builtin_ia32_pmuludq512:
Result = APSInt(llvm::APIntOps::muluExtended(Elem1, Elem2),
/*IsUnsigned=*/true);
Result = APSInt(llvm::APIntOps::muluExtended(Elem1, Elem2), true);
break;
case clang::X86::BI__builtin_ia32_pmuldq128:
case clang::X86::BI__builtin_ia32_pmuldq256:
case clang::X86::BI__builtin_ia32_pmuldq512:
Result = APSInt(llvm::APIntOps::mulsExtended(Elem1, Elem2),
/*IsUnsigned=*/false);
Result = APSInt(llvm::APIntOps::mulsExtended(Elem1, Elem2), false);
break;
}
INT_TYPE_SWITCH_NO_BOOL(DstElemT,
{ Dst.elem<T>(DstElem) = static_cast<T>(Result); });
++DstElem;
INT_TYPE_SWITCH_NO_BOOL(ElemT,
{ Dst.elem<T>(I) = static_cast<T>(Result); });
}
Dst.initializeAllElements();
@ -2783,40 +2774,6 @@ static bool interp__builtin_elementwise_fma(InterpState &S, CodePtr OpPC,
return true;
}
/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
static bool interp__builtin_select(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
const Pointer &RHS = S.Stk.pop<Pointer>();
const Pointer &LHS = S.Stk.pop<Pointer>();
PrimType MaskT = *S.getContext().classify(Call->getArg(0));
APSInt Mask = popToAPSInt(S.Stk, MaskT);
const Pointer &Dst = S.Stk.peek<Pointer>();
assert(LHS.getNumElems() == RHS.getNumElems());
assert(LHS.getNumElems() == Dst.getNumElems());
unsigned NumElems = LHS.getNumElems();
PrimType ElemT = LHS.getFieldDesc()->getPrimType();
PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
for (unsigned I = 0; I != NumElems; ++I) {
if (ElemT == PT_Float) {
assert(DstElemT == PT_Float);
Dst.elem<Floating>(I) =
Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);
} else {
APSInt Elem;
INT_TYPE_SWITCH(ElemT, {
Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();
});
INT_TYPE_SWITCH_NO_BOOL(DstElemT,
{ Dst.elem<T>(I) = static_cast<T>(Elem); });
}
}
Dst.initializeAllElements();
return true;
}
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@ -3247,38 +3204,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case clang::X86::BI__builtin_ia32_pmuldq512:
case clang::X86::BI__builtin_ia32_pmuludq128:
case clang::X86::BI__builtin_ia32_pmuludq256:
case clang::X86::BI__builtin_ia32_pmuludq512:
return interp__builtin_ia32_pmul(S, OpPC, Call, BuiltinID);
case Builtin::BI__builtin_elementwise_fma:
return interp__builtin_elementwise_fma(S, OpPC, Call);
case X86::BI__builtin_ia32_selectb_128:
case X86::BI__builtin_ia32_selectb_256:
case X86::BI__builtin_ia32_selectb_512:
case X86::BI__builtin_ia32_selectw_128:
case X86::BI__builtin_ia32_selectw_256:
case X86::BI__builtin_ia32_selectw_512:
case X86::BI__builtin_ia32_selectd_128:
case X86::BI__builtin_ia32_selectd_256:
case X86::BI__builtin_ia32_selectd_512:
case X86::BI__builtin_ia32_selectq_128:
case X86::BI__builtin_ia32_selectq_256:
case X86::BI__builtin_ia32_selectq_512:
case X86::BI__builtin_ia32_selectph_128:
case X86::BI__builtin_ia32_selectph_256:
case X86::BI__builtin_ia32_selectph_512:
case X86::BI__builtin_ia32_selectpbf_128:
case X86::BI__builtin_ia32_selectpbf_256:
case X86::BI__builtin_ia32_selectpbf_512:
case X86::BI__builtin_ia32_selectps_128:
case X86::BI__builtin_ia32_selectps_256:
case X86::BI__builtin_ia32_selectps_512:
case X86::BI__builtin_ia32_selectpd_128:
case X86::BI__builtin_ia32_selectpd_256:
case X86::BI__builtin_ia32_selectpd_512:
return interp__builtin_select(S, OpPC, Call);
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)

View File

@ -341,8 +341,6 @@ public:
QualType getType() const {
if (isTypeidPointer())
return QualType(Typeid.TypeInfoType, 0);
if (isFunctionPointer())
return asFunctionPointer().getFunction()->getDecl()->getType();
if (inPrimitiveArray() && Offset != asBlockPointer().Base) {
// Unfortunately, complex and vector types are not array types in clang,

View File

@ -11669,24 +11669,13 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case clang::X86::BI__builtin_ia32_pmulhuw512:
case clang::X86::BI__builtin_ia32_pmulhw128:
case clang::X86::BI__builtin_ia32_pmulhw256:
case clang::X86::BI__builtin_ia32_pmulhw512:
case clang::X86::BI__builtin_ia32_psllv2di:
case clang::X86::BI__builtin_ia32_psllv4di:
case clang::X86::BI__builtin_ia32_psllv4si:
case clang::X86::BI__builtin_ia32_psllv8si:
case clang::X86::BI__builtin_ia32_psrav4si:
case clang::X86::BI__builtin_ia32_psrav8si:
case clang::X86::BI__builtin_ia32_psrlv2di:
case clang::X86::BI__builtin_ia32_psrlv4di:
case clang::X86::BI__builtin_ia32_psrlv4si:
case clang::X86::BI__builtin_ia32_psrlv8si:{
case clang::X86::BI__builtin_ia32_pmulhw512: {
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
return false;
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
unsigned SourceLen = SourceLHS.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen);
@ -11698,12 +11687,12 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_elementwise_add_sat:
ResultElements.push_back(APValue(
APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS),
DestUnsigned)));
DestEltTy->isUnsignedIntegerOrEnumerationType())));
break;
case Builtin::BI__builtin_elementwise_sub_sat:
ResultElements.push_back(APValue(
APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS),
DestUnsigned)));
DestEltTy->isUnsignedIntegerOrEnumerationType())));
break;
case clang::X86::BI__builtin_ia32_pmulhuw128:
case clang::X86::BI__builtin_ia32_pmulhuw256:
@ -11717,40 +11706,6 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhs(LHS, RHS),
/*isUnsigned=*/false)));
break;
case clang::X86::BI__builtin_ia32_psllv2di:
case clang::X86::BI__builtin_ia32_psllv4di:
case clang::X86::BI__builtin_ia32_psllv4si:
case clang::X86::BI__builtin_ia32_psllv8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.shl(RHS.getZExtValue()), DestUnsigned)));
break;
case clang::X86::BI__builtin_ia32_psrav4si:
case clang::X86::BI__builtin_ia32_psrav8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(LHS.ashr(RHS.getBitWidth() - 1), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.ashr(RHS.getZExtValue()), DestUnsigned)));
break;
case clang::X86::BI__builtin_ia32_psrlv2di:
case clang::X86::BI__builtin_ia32_psrlv4di:
case clang::X86::BI__builtin_ia32_psrlv4si:
case clang::X86::BI__builtin_ia32_psrlv8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.lshr(RHS.getZExtValue()), DestUnsigned)));
break;
}
}

View File

@ -174,9 +174,6 @@ protected:
DefineStd(Builder, "unix", Opts);
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
if (Opts.C11)
Builder.defineMacro("__STDC_NO_THREADS__");
}
public:

View File

@ -73,54 +73,21 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,
// Casts:
if (auto const *ce = dyn_cast<CastExpr>(expr)) {
if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
cgm.emitExplicitCastExprType(ece);
if (isa<ExplicitCastExpr>(ce)) {
cgm.errorNYI(expr->getSourceRange(),
"emitPointerWithAlignment: explicit cast");
return Address::invalid();
}
switch (ce->getCastKind()) {
// Non-converting casts (but not C's implicit conversion from void*).
case CK_BitCast:
case CK_NoOp:
case CK_AddressSpaceConversion: {
if (const auto *ptrTy =
ce->getSubExpr()->getType()->getAs<PointerType>()) {
if (ptrTy->getPointeeType()->isVoidType())
break;
LValueBaseInfo innerBaseInfo;
assert(!cir::MissingFeatures::opTBAA());
Address addr =
emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
if (baseInfo)
*baseInfo = innerBaseInfo;
if (isa<ExplicitCastExpr>(ce)) {
LValueBaseInfo targetTypeBaseInfo;
const QualType pointeeType = expr->getType()->getPointeeType();
const CharUnits align =
cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
// If the source l-value is opaque, honor the alignment of the
// casted-to type.
if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
if (baseInfo)
baseInfo->mergeForCast(targetTypeBaseInfo);
addr = Address(addr.getPointer(), addr.getElementType(), align);
}
}
assert(!cir::MissingFeatures::sanitizers());
const mlir::Type eltTy =
convertTypeForMem(expr->getType()->getPointeeType());
addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
addr, eltTy);
assert(!cir::MissingFeatures::addressSpace());
return addr;
}
break;
}
cgm.errorNYI(expr->getSourceRange(),
"emitPointerWithAlignment: noop cast");
return Address::invalid();
} break;
// Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
case CK_ArrayToPointerDecay:
@ -584,37 +551,6 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
return RValue::get(nullptr);
}
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
assert(!cir::MissingFeatures::weakRefReference());
return cgm.getAddrOfFunction(gd);
}
static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,
GlobalDecl gd) {
const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl());
cir::FuncOp funcOp = emitFunctionDeclPointer(cgf.cgm, gd);
mlir::Location loc = cgf.getLoc(e->getSourceRange());
CharUnits align = cgf.getContext().getDeclAlign(fd);
assert(!cir::MissingFeatures::sanitizers());
mlir::Type fnTy = funcOp.getFunctionType();
mlir::Type ptrTy = cir::PointerType::get(fnTy);
mlir::Value addr = cgf.getBuilder().create<cir::GetGlobalOp>(
loc, ptrTy, funcOp.getSymName());
if (funcOp.getFunctionType() != cgf.convertType(fd->getType())) {
fnTy = cgf.convertType(fd->getType());
ptrTy = cir::PointerType::get(fnTy);
addr = cir::CastOp::create(cgf.getBuilder(), addr.getLoc(), ptrTy,
cir::CastKind::bitcast, addr);
}
return cgf.makeAddrLValue(Address(addr, fnTy, align), e->getType(),
AlignmentSource::Decl);
}
LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
const NamedDecl *nd = e->getDecl();
QualType ty = e->getType();
@ -671,16 +607,6 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
return emitLValue(bd->getBinding());
}
if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
LValue lv = emitFunctionDeclLValue(*this, e, fd);
// Emit debuginfo for the function declaration if the target wants to.
if (getContext().getTargetInfo().allowDebugInfoForExternalRef())
assert(!cir::MissingFeatures::generateDebugInfo());
return lv;
}
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
return LValue();
}
@ -1475,6 +1401,11 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot) {
llvm_unreachable("bad evaluation kind");
}
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
assert(!cir::MissingFeatures::weakRefReference());
return cgm.getAddrOfFunction(gd);
}
// Detect the unusual situation where an inline version is shadowed by a
// non-inline version. In that case we should pick the external one
// everywhere. That's GCC behavior too.

View File

@ -1905,8 +1905,6 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
Visit(subExpr));
}
case CK_FunctionToPointerDecay:
return cgf.emitLValue(subExpr).getPointer();
default:
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),

View File

@ -103,9 +103,6 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
PtrDiffTy =
cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
theModule->setAttr(
cir::CIRDialect::getSourceLanguageAttrName(),
cir::SourceLanguageAttr::get(&mlirContext, getCIRSourceLanguage()));
theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
builder.getStringAttr(getTriple().str()));
@ -513,23 +510,6 @@ void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
assert(!cir::MissingFeatures::setTargetAttributes());
}
cir::SourceLanguage CIRGenModule::getCIRSourceLanguage() const {
using ClangStd = clang::LangStandard;
using CIRLang = cir::SourceLanguage;
auto opts = getLangOpts();
if (opts.CPlusPlus)
return CIRLang::CXX;
if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
opts.LangStd == ClangStd::lang_c89 ||
opts.LangStd == ClangStd::lang_gnu89)
return CIRLang::C;
// TODO(cir): support remaining source languages.
assert(!cir::MissingFeatures::sourceLanguageCases());
errorNYI("CIR does not yet support the given source language");
}
static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
// Set linkage and visibility in case we never see a definition.
LinkageInfo lv = nd->getLinkageAndVisibility();

View File

@ -461,9 +461,6 @@ private:
void replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF);
void setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op);
/// Map source language used to a CIR attribute.
cir::SourceLanguage getCIRSourceLanguage() const;
};
} // namespace CIRGen

View File

@ -424,44 +424,6 @@ cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return elementTypeCheck;
}
//===----------------------------------------------------------------------===//
// CIR VTableAttr
//===----------------------------------------------------------------------===//
LogicalResult cir::VTableAttr::verify(
llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type type,
mlir::ArrayAttr data) {
auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
if (!sTy)
return emitError() << "expected !cir.record type result";
if (sTy.getMembers().empty() || data.empty())
return emitError() << "expected record type with one or more subtype";
if (cir::ConstRecordAttr::verify(emitError, type, data).failed())
return failure();
for (const auto &element : data.getAsRange<mlir::Attribute>()) {
const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
if (!constArrayAttr)
return emitError() << "expected constant array subtype";
LogicalResult eltTypeCheck = success();
auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());
arrayElts.walkImmediateSubElements(
[&](mlir::Attribute attr) {
if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))
return;
eltTypeCheck = emitError()
<< "expected GlobalViewAttr or ConstPtrAttr";
},
[&](mlir::Type type) {});
if (eltTypeCheck.failed())
return eltTypeCheck;
}
return success();
}
//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

View File

@ -342,8 +342,7 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
cir::GlobalViewAttr, cir::PoisonAttr, cir::VTableAttr>(
attrType))
cir::GlobalViewAttr, cir::PoisonAttr>(attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");

View File

@ -4,7 +4,6 @@ add_clang_library(MLIRCIRTransforms
FlattenCFG.cpp
HoistAllocas.cpp
LoweringPrepare.cpp
GotoSolver.cpp
DEPENDS
MLIRCIRPassIncGen

View File

@ -1,57 +0,0 @@
//====- GotoSolver.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "PassDetail.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"
#include "llvm/Support/TimeProfiler.h"
#include <memory>
using namespace mlir;
using namespace cir;
namespace {
struct GotoSolverPass : public GotoSolverBase<GotoSolverPass> {
GotoSolverPass() = default;
void runOnOperation() override;
};
static void process(cir::FuncOp func) {
mlir::OpBuilder rewriter(func.getContext());
llvm::StringMap<Block *> labels;
llvm::SmallVector<cir::GotoOp, 4> gotos;
func.getBody().walk([&](mlir::Operation *op) {
if (auto lab = dyn_cast<cir::LabelOp>(op)) {
// Will construct a string copy inplace. Safely erase the label
labels.try_emplace(lab.getLabel(), lab->getBlock());
lab.erase();
} else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {
gotos.push_back(goTo);
}
});
for (auto goTo : gotos) {
mlir::OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPoint(goTo);
Block *dest = labels[goTo.getLabel()];
cir::BrOp::create(rewriter, goTo.getLoc(), dest);
goTo.erase();
}
}
void GotoSolverPass::runOnOperation() {
llvm::TimeTraceScope scope("Goto Solver");
getOperation()->walk(&process);
}
} // namespace
std::unique_ptr<Pass> mlir::createGotoSolverPass() {
return std::make_unique<GotoSolverPass>();
}

View File

@ -45,7 +45,6 @@ namespace mlir {
void populateCIRPreLoweringPasses(OpPassManager &pm) {
pm.addPass(createHoistAllocasPass());
pm.addPass(createCIRFlattenCFGPass());
pm.addPass(createGotoSolverPass());
}
} // namespace mlir

View File

@ -4184,14 +4184,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
break;
}
if (auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(Ty->getOriginalDecl())) {
CXXRecordDecl *TemplateDecl =
CTSD->getSpecializedTemplate()->getTemplatedDecl();
RegionMap[TemplateDecl].reset(RealDecl);
} else {
RegionMap[RD].reset(RealDecl);
}
RegionMap[RD].reset(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))

View File

@ -977,8 +977,6 @@ public:
ApplyInlineDebugLocation(CodeGenFunction &CGF, GlobalDecl InlinedFn);
/// Restore everything back to the original state.
~ApplyInlineDebugLocation();
ApplyInlineDebugLocation(const ApplyInlineDebugLocation &) = delete;
ApplyInlineDebugLocation &operator=(ApplyInlineDebugLocation &) = delete;
};
class SanitizerDebugLocation {
@ -990,8 +988,6 @@ public:
ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
SanitizerHandler Handler);
~SanitizerDebugLocation();
SanitizerDebugLocation(const SanitizerDebugLocation &) = delete;
SanitizerDebugLocation &operator=(SanitizerDebugLocation &) = delete;
};
} // namespace CodeGen

View File

@ -466,14 +466,6 @@ llvm::Constant *CodeGenModule::getConstantSignedPointer(
OtherDiscriminator);
}
llvm::Constant *
CodeGen::getConstantSignedPointer(CodeGenModule &CGM, llvm::Constant *Pointer,
unsigned Key, llvm::Constant *StorageAddress,
llvm::ConstantInt *OtherDiscriminator) {
return CGM.getConstantSignedPointer(Pointer, Key, StorageAddress,
OtherDiscriminator);
}
/// If applicable, sign a given constant function pointer with the ABI rules for
/// functionType.
llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,

View File

@ -1409,6 +1409,13 @@ void ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a system include directory to CC1 arguments.
void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args, const Twine &Path) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a system include directory with extern "C"
/// semantics to CC1 arguments.
///
@ -1431,14 +1438,6 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, Path);
}
/// Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args,
const Twine &Path) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a list of system framework directories to CC1.
void ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,

View File

@ -534,14 +534,7 @@ void Flang::addTargetOptions(const ArgList &Args,
}
Args.addAllArgs(CmdArgs,
{options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
options::OPT_fatomic_ignore_denormal_mode,
options::OPT_fno_atomic_ignore_denormal_mode,
options::OPT_fatomic_fine_grained_memory,
options::OPT_fno_atomic_fine_grained_memory,
options::OPT_fatomic_remote_memory,
options::OPT_fno_atomic_remote_memory,
options::OPT_munsafe_fp_atomics});
{options::OPT_fverbose_asm, options::OPT_fno_verbose_asm});
}
void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,

View File

@ -2123,11 +2123,10 @@ void Generic_GCC::GCCInstallationDetector::init(
StringRef TripleText =
llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
SelectedInstallation.Version = GCCVersion::Parse(VersionText);
SelectedInstallation.GCCTriple.setTriple(TripleText);
SelectedInstallation.GCCInstallPath = std::string(InstallDir);
SelectedInstallation.GCCParentLibPath =
SelectedInstallation.GCCInstallPath + "/../../..";
Version = GCCVersion::Parse(VersionText);
GCCTriple.setTriple(TripleText);
GCCInstallPath = std::string(InstallDir);
GCCParentLibPath = GCCInstallPath + "/../../..";
IsValid = true;
}
return;
@ -2187,7 +2186,7 @@ void Generic_GCC::GCCInstallationDetector::init(
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
SelectedInstallation.Version = VersionZero;
Version = VersionZero;
for (const std::string &Prefix : Prefixes) {
auto &VFS = D.getVFS();
if (!VFS.exists(Prefix))
@ -2215,7 +2214,7 @@ void Generic_GCC::GCCInstallationDetector::init(
}
// Skip other prefixes once a GCC installation is found.
if (SelectedInstallation.Version > VersionZero)
if (Version > VersionZero)
break;
}
}
@ -2224,17 +2223,14 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
for (const auto &InstallPath : CandidateGCCInstallPaths)
OS << "Found candidate GCC installation: " << InstallPath << "\n";
if (!SelectedInstallation.GCCInstallPath.empty())
OS << "Selected GCC installation: " << SelectedInstallation.GCCInstallPath
<< "\n";
if (!GCCInstallPath.empty())
OS << "Selected GCC installation: " << GCCInstallPath << "\n";
for (const auto &Multilib : Multilibs)
OS << "Candidate multilib: " << Multilib << "\n";
if (Multilibs.size() != 0 ||
!SelectedInstallation.SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedInstallation.SelectedMultilib
<< "\n";
if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedMultilib << "\n";
}
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
@ -2772,50 +2768,14 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
}
Multilibs = Detected.Multilibs;
SelectedInstallation.SelectedMultilib =
Detected.SelectedMultilibs.empty() ? Multilib()
: Detected.SelectedMultilibs.back();
SelectedMultilib = Detected.SelectedMultilibs.empty()
? Multilib()
: Detected.SelectedMultilibs.back();
BiarchSibling = Detected.BiarchSibling;
return true;
}
bool Generic_GCC::GCCInstallationDetector::SelectGCCInstallationDirectory(
const SmallVector<Generic_GCC::GCCInstallCandidate, 3> &Installations,
const ArgList &Args,
Generic_GCC::GCCInstallCandidate &SelectedInstallation) const {
if (Installations.empty())
return false;
SelectedInstallation =
*max_element(Installations, [](const auto &Max, const auto &I) {
return I.Version > Max.Version;
});
// FIXME Start selecting installation with libstdc++ in clang 22,
// using the current way of selecting the installation as a fallback
// only. For now, warn if the installation with libstdc++ differs
// from SelectedInstallation.
const GCCInstallCandidate *InstallWithIncludes = nullptr;
for (const auto &I : Installations) {
if ((!InstallWithIncludes || I.Version > InstallWithIncludes->Version) &&
GCCInstallationHasLibStdcxxIncludePaths(I, Args))
InstallWithIncludes = &I;
}
if (InstallWithIncludes && SelectedInstallation.GCCInstallPath !=
InstallWithIncludes->GCCInstallPath)
D.Diag(diag::warn_drv_gcc_install_dir_libstdcxx)
<< InstallWithIncludes->GCCInstallPath
<< SelectedInstallation.GCCInstallPath;
// TODO Warn if SelectedInstallation does not contain libstdc++ includes
// although compiler flags indicate that it is required (C++ compilation,
// libstdc++ not explicitly disabled).
return true;
}
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
@ -2845,7 +2805,6 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
TargetTriple.getVendor() == llvm::Triple::Freescale ||
TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
SmallVector<GCCInstallCandidate, 3> Installations;
for (auto &Suffix : Suffixes) {
if (!Suffix.Active)
continue;
@ -2863,31 +2822,23 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= SelectedInstallation.Version && IsValid)
if (CandidateVersion <= Version)
continue;
if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
NeedsBiarchSuffix))
continue;
GCCInstallCandidate Installation;
Installation.Version = CandidateVersion;
Installation.GCCTriple.setTriple(CandidateTriple);
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of
// using LI to ensure stable path separators across Windows and
// Linux.
Installation.GCCInstallPath =
(LibDir + "/" + LibSuffix + "/" + VersionText).str();
Installation.GCCParentLibPath =
(Installation.GCCInstallPath + "/../" + Suffix.ReversePath).str();
Installation.SelectedMultilib = getMultilib();
Installations.push_back(Installation);
GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
IsValid = true;
}
}
IsValid |=
SelectGCCInstallationDirectory(Installations, Args, SelectedInstallation);
}
bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
@ -2965,12 +2916,10 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
NeedsBiarchSuffix))
continue;
SelectedInstallation.Version =
GCCVersion::Parse(ActiveVersion.second);
SelectedInstallation.GCCInstallPath = GentooPath;
SelectedInstallation.GCCParentLibPath =
GentooPath + std::string("/../../..");
SelectedInstallation.GCCTriple.setTriple(ActiveVersion.first);
Version = GCCVersion::Parse(ActiveVersion.second);
GCCInstallPath = GentooPath;
GCCParentLibPath = GentooPath + std::string("/../../..");
GCCTriple.setTriple(ActiveVersion.first);
IsValid = true;
return true;
}
@ -3173,9 +3122,8 @@ void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
// gcc TOOL_INCLUDE_DIR.
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
std::string LibPath(GCCInstallation.getParentLibPath());
ToolChain::addSystemInclude(DriverArgs, CC1Args,
Twine(LibPath) + "/../" + GCCTriple.str() +
"/include");
addSystemInclude(DriverArgs, CC1Args,
Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
@ -3262,14 +3210,12 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
return;
}
static bool addLibStdCXXIncludePaths(llvm::vfs::FileSystem &vfs,
Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian = false) {
if (!vfs.exists(IncludeDir))
bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian) const {
if (!getVFS().exists(IncludeDir))
return false;
// Debian native gcc uses g++-multiarch-incdir.diff which uses
@ -3281,48 +3227,39 @@ static bool addLibStdCXXIncludePaths(llvm::vfs::FileSystem &vfs,
std::string Path =
(Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
.str();
if (DetectDebian && !vfs.exists(Path))
if (DetectDebian && !getVFS().exists(Path))
return false;
// GPLUSPLUS_INCLUDE_DIR
ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir);
addSystemInclude(DriverArgs, CC1Args, IncludeDir);
// GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
// include directory.
if (DetectDebian)
ToolChain::addSystemInclude(DriverArgs, CC1Args, Path);
addSystemInclude(DriverArgs, CC1Args, Path);
else if (!Triple.empty())
ToolChain::addSystemInclude(DriverArgs, CC1Args,
IncludeDir + "/" + Triple + IncludeSuffix);
addSystemInclude(DriverArgs, CC1Args,
IncludeDir + "/" + Triple + IncludeSuffix);
// GPLUSPLUS_BACKWARD_INCLUDE_DIR
ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
return true;
}
bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian) const {
return ::addLibStdCXXIncludePaths(getVFS(), IncludeDir, Triple, IncludeSuffix,
DriverArgs, CC1Args, DetectDebian);
}
bool Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
llvm::vfs::FileSystem &vfs, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args, StringRef DebianMultiarch) const {
bool Generic_GCC::addGCCLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const {
assert(GCCInstallation.isValid());
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = getParentLibPath();
StringRef InstallDir = getInstallPath();
StringRef TripleStr = getTriple().str();
const Multilib &Multilib = getMultilib();
const GCCVersion &Version = getVersion();
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
// Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
if (::addLibStdCXXIncludePaths(
vfs,
if (addLibStdCXXIncludePaths(
LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
@ -3330,24 +3267,22 @@ bool Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
// Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
// empty). Like above but for GCC built with
// --enable-version-specific-runtime-libs.
if (::addLibStdCXXIncludePaths(vfs,
LibDir.str() + "/gcc/" + TripleStr + "/" +
Version.Text + "/include/c++/",
TripleStr, Multilib.includeSuffix(),
DriverArgs, CC1Args))
if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
Version.Text + "/include/c++/",
TripleStr, Multilib.includeSuffix(), DriverArgs,
CC1Args))
return true;
// Detect Debian g++-multiarch-incdir.diff.
if (::addLibStdCXXIncludePaths(
vfs, LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(), DriverArgs, CC1Args,
/*Debian=*/true))
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(),
DriverArgs, CC1Args, /*Debian=*/true))
return true;
// Try /../include/c++/$version (gcc --print-multiarch is empty).
if (::addLibStdCXXIncludePaths(
vfs, LibDir.str() + "/../include/c++/" + Version.Text, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
TripleStr, Multilib.includeSuffix(), DriverArgs,
CC1Args))
return true;
// Otherwise, fall back on a bunch of options which don't use multiarch
@ -3362,50 +3297,20 @@ bool Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
if (::addLibStdCXXIncludePaths(vfs, IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs,
CC1Args))
if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
}
return false;
}
bool Generic_GCC::GCCInstallationDetector::
GCCInstallationHasLibStdcxxIncludePaths(
const GCCInstallCandidate &GCCInstallation,
const llvm::opt::ArgList &DriverArgs) const {
StringRef DebianMultiarch =
TripleToDebianMultiarch(GCCInstallation.getTriple());
// The following function checks for libstdc++ include paths and
// adds them to the provided argument list. Here we just need the
// check.
llvm::opt::ArgStringList dummyCC1Args;
return GCCInstallation.addGCCLibStdCxxIncludePaths(
D.getVFS(), DriverArgs, dummyCC1Args, DebianMultiarch);
}
bool Generic_GCC::addGCCLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
assert(GCCInstallation.isValid());
// Detect Debian g++-multiarch-incdir.diff.
StringRef DebianMultiarch =
GCCInstallation.TripleToDebianMultiarch(GCCInstallation.getTriple());
return GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
getVFS(), DriverArgs, CC1Args, DebianMultiarch);
}
void
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (!GCCInstallation.isValid())
return;
GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
getVFS(), DriverArgs, CC1Args, GCCInstallation.getTriple().str());
if (GCCInstallation.isValid()) {
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
GCCInstallation.getTriple().str());
}
}
llvm::opt::DerivedArgList *

View File

@ -184,18 +184,46 @@ public:
bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
};
struct GCCInstallCandidate {
/// This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
bool IsValid;
llvm::Triple GCCTriple;
const Driver &D;
// FIXME: These might be better as path objects.
std::string GCCInstallPath;
std::string GCCParentLibPath;
llvm::Triple GCCTriple;
/// The primary multilib appropriate for the given flags.
Multilib SelectedMultilib;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
std::optional<Multilib> BiarchSibling;
GCCVersion Version;
// We retain the list of install paths that were considered and rejected in
// order to print out detailed information in verbose mode.
std::set<std::string> CandidateGCCInstallPaths;
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
// Gentoo-specific toolchain configurations are stored here.
const std::string GentooConfigDir = "/etc/env.d/gcc";
public:
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
/// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
/// Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const { return GCCTriple; }
@ -208,88 +236,6 @@ public:
/// Get the detected Multilib
const Multilib &getMultilib() const { return SelectedMultilib; }
/// Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }
bool addGCCLibStdCxxIncludePaths(llvm::vfs::FileSystem &vfs,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const;
};
/// This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
bool IsValid;
const Driver &D;
GCCInstallCandidate SelectedInstallation;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
std::optional<Multilib> BiarchSibling;
// We retain the list of install paths that were considered and rejected in
// order to print out detailed information in verbose mode.
std::set<std::string> CandidateGCCInstallPaths;
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
// Gentoo-specific toolchain configurations are stored here.
const std::string GentooConfigDir = "/etc/env.d/gcc";
public:
/// Function for converting a triple to a Debian multiarch. The
/// toolchains use this to adjust the target specific component of
/// include paths for Debian.
std::function<StringRef(const llvm::Triple &)> TripleToDebianMultiarch =
[](const llvm::Triple &T) {
StringRef S = T.str();
return S;
};
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
// TODO Replace isValid by changing SelectedInstallation into
// std::optional<SelectedInstallation>
// and move all accessors for fields of GCCInstallCandidate into
// that struct.
/// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
const GCCInstallCandidate &getSelectedInstallation() const {
return SelectedInstallation;
}
/// Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const {
return SelectedInstallation.GCCTriple;
}
/// Get the detected GCC installation path.
StringRef getInstallPath() const {
return SelectedInstallation.GCCInstallPath;
}
/// Get the detected GCC parent lib path.
StringRef getParentLibPath() const {
return SelectedInstallation.GCCParentLibPath;
}
/// Get the detected Multilib
const Multilib &getMultilib() const {
return SelectedInstallation.SelectedMultilib;
}
/// Get the whole MultilibSet
const MultilibSet &getMultilibs() const { return Multilibs; }
@ -298,9 +244,7 @@ public:
bool getBiarchSibling(Multilib &M) const;
/// Get the detected GCC version string.
const GCCVersion &getVersion() const {
return SelectedInstallation.Version;
}
const GCCVersion &getVersion() const { return Version; }
/// Print information about the detected GCC installation.
void print(raw_ostream &OS) const;
@ -318,19 +262,6 @@ public:
SmallVectorImpl<std::string> &Prefixes,
StringRef SysRoot);
/// Checks if the \p GCCInstallation has libstdc++ include
/// directories.
bool GCCInstallationHasLibStdcxxIncludePaths(
const GCCInstallCandidate &GCCInstallation,
const llvm::opt::ArgList &DriverArgs) const;
/// Select a GCC installation directory from \p Installations and
/// set \p SelectedInstallation accordingly.
bool SelectGCCInstallationDirectory(
const SmallVector<GCCInstallCandidate, 3> &Installations,
const llvm::opt::ArgList &Args,
GCCInstallCandidate &SelectedInstallation) const;
bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args, StringRef Path,
bool NeedsBiarchSuffix = false);
@ -417,7 +348,8 @@ protected:
llvm::opt::ArgStringList &CC1Args) const;
bool addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC) const;
llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const;
bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,

View File

@ -173,72 +173,24 @@ bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
return true;
}
void getSpirvExtOperand(StringRef SpvExtensionArg, raw_ostream &out) {
// The extensions that are commented out are supported in DXC, but the SPIR-V
// backend does not know about them yet.
static const std::vector<StringRef> DxcSupportedExtensions = {
"SPV_KHR_16bit_storage", "SPV_KHR_device_group",
"SPV_KHR_fragment_shading_rate", "SPV_KHR_multiview",
"SPV_KHR_post_depth_coverage", "SPV_KHR_non_semantic_info",
"SPV_KHR_shader_draw_parameters", "SPV_KHR_ray_tracing",
"SPV_KHR_shader_clock", "SPV_EXT_demote_to_helper_invocation",
"SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered",
"SPV_EXT_fragment_invocation_density",
"SPV_EXT_fragment_shader_interlock", "SPV_EXT_mesh_shader",
"SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer",
// "SPV_AMD_shader_early_and_late_fragment_tests",
"SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type",
"SPV_KHR_ray_query", "SPV_EXT_shader_image_int64",
"SPV_KHR_fragment_shader_barycentric", "SPV_KHR_physical_storage_buffer",
"SPV_KHR_vulkan_memory_model",
// "SPV_KHR_compute_shader_derivatives",
// "SPV_KHR_maximal_reconvergence",
"SPV_KHR_float_controls", "SPV_NV_shader_subgroup_partitioned",
// "SPV_KHR_quad_control"
};
if (SpvExtensionArg.starts_with("SPV_")) {
out << "+" << SpvExtensionArg;
return;
}
if (SpvExtensionArg.compare_insensitive("DXC") == 0) {
bool first = true;
std::string Operand;
for (StringRef E : DxcSupportedExtensions) {
if (!first)
out << ",";
else
first = false;
out << "+" << E;
}
return;
}
out << SpvExtensionArg;
return;
}
SmallString<1024> getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
std::string getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
if (SpvExtensionArgs.empty()) {
return StringRef("-spirv-ext=all");
return "-spirv-ext=all";
}
llvm::SmallString<1024> LlvmOption;
raw_svector_ostream out(LlvmOption);
out << "-spirv-ext=";
getSpirvExtOperand(SpvExtensionArgs[0], out);
std::string LlvmOption =
(Twine("-spirv-ext=+") + SpvExtensionArgs.front()).str();
SpvExtensionArgs = SpvExtensionArgs.slice(1);
for (StringRef Extension : SpvExtensionArgs) {
out << ",";
getSpirvExtOperand(Extension, out);
for (auto Extension : SpvExtensionArgs) {
if (Extension != "KHR")
Extension = (Twine("+") + Extension).str();
LlvmOption = (Twine(LlvmOption) + "," + Extension).str();
}
return LlvmOption;
}
bool isValidSPIRVExtensionName(const std::string &str) {
std::regex pattern("dxc|DXC|khr|KHR|SPV_[a-zA-Z0-9_]+");
std::regex pattern("KHR|SPV_[a-zA-Z0-9_]+");
return std::regex_match(str, pattern);
}
@ -419,7 +371,7 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
std::vector<std::string> SpvExtensionArgs =
Args.getAllArgValues(options::OPT_fspv_extension_EQ);
if (checkExtensionArgsAreValid(SpvExtensionArgs, getDriver())) {
SmallString<1024> LlvmOption = getSpirvExtArg(SpvExtensionArgs);
std::string LlvmOption = getSpirvExtArg(SpvExtensionArgs);
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_mllvm),
LlvmOption);
}

View File

@ -71,13 +71,6 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
StringRef TripleStr = T.str();
StringRef DebianMultiarch =
T.getArch() == llvm::Triple::x86 ? "i386-gnu" : TripleStr;
return DebianMultiarch;
};
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
SelectedMultilibs.assign({GCCInstallation.getMultilib()});
@ -214,7 +207,12 @@ void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
if (!GCCInstallation.isValid())
return;
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
StringRef TripleStr = GCCInstallation.getTriple().str();
StringRef DebianMultiarch =
GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"
: TripleStr;
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);
}
void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {

View File

@ -211,13 +211,6 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
StringRef TripleStr = T.str();
StringRef DebianMultiarch =
T.getArch() == llvm::Triple::x86 ? "i386-linux-gnu" : TripleStr;
return DebianMultiarch;
};
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
SelectedMultilibs.assign({GCCInstallation.getMultilib()});
@ -700,15 +693,22 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
if (!GCCInstallation.isValid())
return;
// Detect Debian g++-multiarch-incdir.diff.
StringRef TripleStr = GCCInstallation.getTriple().str();
StringRef DebianMultiarch =
GCCInstallation.getTriple().getArch() == llvm::Triple::x86
? "i386-linux-gnu"
: TripleStr;
// Try generic GCC detection first.
if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
DebianMultiarch))
return;
StringRef LibDir = GCCInstallation.getParentLibPath();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const std::string LibStdCXXIncludePathCandidates[] = {
// Android standalone toolchain has C++ headers in yet another place.
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,

View File

@ -193,8 +193,10 @@ void Managarm::addLibStdCxxIncludePaths(
if (!GCCInstallation.isValid())
return;
StringRef TripleStr = GCCInstallation.getTriple().str();
// Try generic GCC detection.
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, TripleStr);
}
SanitizerMask Managarm::getSupportedSanitizers() const {

View File

@ -3721,7 +3721,7 @@ _mm_maskstore_epi64(long long *__X, __m128i __M, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sllv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv8si((__v8si)__X, (__v8si)__Y);
@ -3743,7 +3743,7 @@ _mm256_sllv_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sllv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv4si((__v4si)__X, (__v4si)__Y);
@ -3765,7 +3765,7 @@ _mm_sllv_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [4 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [4 x i64] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_sllv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv4di((__v4di)__X, (__v4di)__Y);
@ -3787,7 +3787,7 @@ _mm256_sllv_epi64(__m256i __X, __m256i __Y)
/// A 128-bit vector of [2 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [2 x i64] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_sllv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv2di((__v2di)__X, (__v2di)__Y);
@ -3810,7 +3810,7 @@ _mm_sllv_epi64(__m128i __X, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srav_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrav8si((__v8si)__X, (__v8si)__Y);
@ -3833,7 +3833,7 @@ _mm256_srav_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srav_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrav4si((__v4si)__X, (__v4si)__Y);
@ -3855,7 +3855,7 @@ _mm_srav_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srlv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv8si((__v8si)__X, (__v8si)__Y);
@ -3877,7 +3877,7 @@ _mm256_srlv_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srlv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv4si((__v4si)__X, (__v4si)__Y);
@ -3899,7 +3899,7 @@ _mm_srlv_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [4 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [4 x i64] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_srlv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv4di((__v4di)__X, (__v4di)__Y);
@ -3921,7 +3921,7 @@ _mm256_srlv_epi64(__m256i __X, __m256i __Y)
/// A 128-bit vector of [2 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [2 x i64] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_srlv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv2di((__v2di)__X, (__v2di)__Y);

View File

@ -5601,10 +5601,8 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
TheCall->getArg(1)->getEndLoc()));
} else if (numElements != numResElements) {
QualType eltType = LHSType->castAs<VectorType>()->getElementType();
resType = resType->isExtVectorType()
? Context.getExtVectorType(eltType, numResElements)
: Context.getVectorType(eltType, numResElements,
VectorKind::Generic);
resType =
Context.getVectorType(eltType, numResElements, VectorKind::Generic);
}
}

View File

@ -800,23 +800,3 @@ namespace ZeroSizeArrayRead {
static_assert(s[0] == '0', ""); // both-error {{not an integral constant expression}} \
// both-note {{read of dereferenced one-past-the-end pointer}}
}
namespace FAM {
char *strchr(const char *, int);
struct A {
char n, a[2];
};
struct B {
int n;
struct A a[]; // both-note {{here}}
};
const struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}};
void foo(void) { int sch = 0 != strchr(b.a[1].a, '\0'); }
int foo2() {
struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}}; // both-error {{initialization of flexible array member is not allowed}}
return 1;
}
}

View File

@ -338,12 +338,3 @@ static void *FooTable[1] = {
}
};
int strcmp(const char *, const char *); // all-note {{passing argument to parameter here}}
#define S "\x01\x02\x03\x04\x05\x06\x07\x08"
const char _str[] = {S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7]};
const unsigned char _str2[] = {S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7]};
const int compared = strcmp(_str, (const char *)_str2); // all-error {{initializer element is not a compile-time constant}}
const int compared2 = strcmp(strcmp, _str); // all-warning {{incompatible pointer types}} \
// all-error {{initializer element is not a compile-time constant}}

View File

@ -15,6 +15,7 @@ using FourFloatsExtVec __attribute__((ext_vector_type(4))) = float;
using FourDoublesExtVec __attribute__((ext_vector_type(4))) = double;
using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128;
// Next a series of tests to make sure these operations are usable in
// constexpr functions. Template instantiations don't emit Winvalid-constexpr,
// so we have to do these as macros.
@ -874,9 +875,3 @@ void BoolVecUsage() {
constexpr auto k = ~FourBoolsExtVec{true, false, true, false};
static_assert(k[0] == false && k[1] == true && k[2] == false && k[3] == true, "");
}
using EightBoolsExtVec __attribute__((ext_vector_type(8))) = bool;
void BoolVecShuffle() {
constexpr EightBoolsExtVec a = __builtin_shufflevector(
FourBoolsExtVec{}, FourBoolsExtVec{}, 0, 1, 2, 3, 4, 5, 6, 7);
}

View File

@ -732,8 +732,3 @@ namespace LocalVarForParmVarDecl {
}
static_assert(foo(), "");
}
namespace PtrPtrCast {
void foo() { ; }
void bar(int *a) { a = (int *)(void *)(foo); }
}

View File

@ -104,15 +104,3 @@ namespace CallScope {
// expected-note {{member call on variable whose lifetime has ended}} \
// ref-note {{member call on object outside its lifetime}}
}
namespace ExprDoubleDestroy {
template <typename T>
constexpr bool test() {
T{}.~T(); // both-note {{lifetime has already ended}}
return true;
}
struct S { int x; };
constexpr bool t = test<S>(); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to}}
}

View File

@ -13,12 +13,7 @@ struct __type_info_implementations {
typedef __unique_impl __impl;
};
class __pointer_type_info {
public:
int __flags = 0;
};
class type_info : public __pointer_type_info {
class type_info {
protected:
typedef __type_info_implementations::__impl __impl;
__impl::__type_name_t __type_name;
@ -45,10 +40,3 @@ constexpr bool test() {
return true;
}
static_assert(test());
int dontcrash() {
auto& pti = static_cast<const std::__pointer_type_info&>(
typeid(int)
);
return pti.__flags == 0 ? 1 : 0;
}

View File

@ -1,47 +0,0 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
void f(void);
void f1() {
(void (*)())f;
}
void f2() {
(*(void (*)(void))f)();
}
void test_lvalue_cast() {
(*(void (*)(int))f)(42);
}
// CIR-LABEL: cir.func{{.*}} @f()
// CIR: cir.func{{.*}} @f1()
// CIR: cir.return{{.*}}
// CIR-LABEL: cir.func{{.*}} @f2()
// CIR: cir.call @f() : () -> ()
// CIR-LABEL: cir.func{{.*}} @test_lvalue_cast()
// CIR: %[[S0:.+]] = {{.*}}@f : !cir.ptr<!cir.func<()>>{{.*}}
// CIR: %[[S1:.+]] = cir.cast{{.*}}%[[S0]] : !cir.ptr<!cir.func<()>>{{.*}}
// CIR: %[[S2:.+]] = cir.const #cir.int<42> : !s32i
// CIR: cir.call %[[S1]](%[[S2]]) : (!cir.ptr<!cir.func<(!s32i)>>, !s32i) -> ()
// LLVM-LABEL: define{{.*}} void @f1()
// LLVM: ret void
// LLVM: define{{.*}} void @f2()
// LLVM: call void @f()
// LLVM: define{{.*}} void @test_lvalue_cast()
// LLVM: call void @f(i32 42)
// OGCG-LABEL: define{{.*}} void @f1()
// OGCG: ret void
// OGCG: define{{.*}} void @f2()
// OGCG: call void @f()
// OGCG: define{{.*}} void @test_lvalue_cast()
// OGCG: call void @f(i32 noundef 42)

View File

@ -1,7 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
@ -29,24 +27,6 @@ err:
// CIR: cir.store [[MINUS]], [[RETVAL]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.br ^bb1
// LLVM: define dso_local i32 @_Z21shouldNotGenBranchReti
// LLVM: [[COND:%.*]] = load i32, ptr {{.*}}, align 4
// LLVM: [[CMP:%.*]] = icmp sgt i32 [[COND]], 5
// LLVM: br i1 [[CMP]], label %[[IFTHEN:.*]], label %[[IFEND:.*]]
// LLVM: [[IFTHEN]]:
// LLVM: br label %[[ERR:.*]]
// LLVM: [[IFEND]]:
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: store i32 0, ptr %[[RETVAL:.*]], align 4
// LLVM: br label %[[BBRET:.*]]
// LLVM: [[BBRET]]:
// LLVM: [[RET:%.*]] = load i32, ptr %[[RETVAL]], align 4
// LLVM: ret i32 [[RET]]
// LLVM: [[ERR]]:
// LLVM: store i32 -1, ptr %[[RETVAL]], align 4
// LLVM: br label %10
// OGCG: define dso_local noundef i32 @_Z21shouldNotGenBranchReti
// OGCG: if.then:
// OGCG: br label %err
@ -71,17 +51,6 @@ err:
// CIR: ^bb1:
// CIR: cir.label "err"
// LLVM: define dso_local i32 @_Z15shouldGenBranchi
// LLVM: br i1 [[CMP:%.*]], label %[[IFTHEN:.*]], label %[[IFEND:.*]]
// LLVM: [[IFTHEN]]:
// LLVM: br label %[[ERR:.*]]
// LLVM: [[IFEND]]:
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: br label %[[ERR]]
// LLVM: [[ERR]]:
// LLVM: ret i32 [[RET:%.*]]
// OGCG: define dso_local noundef i32 @_Z15shouldGenBranchi
// OGCG: if.then:
// OGCG: br label %err
@ -109,15 +78,6 @@ end2:
// CIR: ^bb[[#BLK3]]:
// CIR: cir.label "end2"
// LLVM: define dso_local void @_Z19severalLabelsInARowi
// LLVM: br label %[[END1:.*]]
// LLVM: [[UNRE:.*]]: ; No predecessors!
// LLVM: br label %[[END2:.*]]
// LLVM: [[END1]]:
// LLVM: br label %[[END2]]
// LLVM: [[END2]]:
// LLVM: ret
// OGCG: define dso_local void @_Z19severalLabelsInARowi
// OGCG: br label %end1
// OGCG: end1:
@ -139,13 +99,6 @@ end:
// CIR: ^bb[[#BLK2:]]:
// CIR: cir.label "end"
// LLVM: define dso_local void @_Z18severalGotosInARowi
// LLVM: br label %[[END:.*]]
// LLVM: [[UNRE:.*]]: ; No predecessors!
// LLVM: br label %[[END]]
// LLVM: [[END]]:
// LLVM: ret void
// OGCG: define dso_local void @_Z18severalGotosInARowi(i32 noundef %a) #0 {
// OGCG: br label %end
// OGCG: end:
@ -173,14 +126,6 @@ extern "C" void multiple_non_case(int v) {
// CIR: cir.call @action2()
// CIR: cir.break
// LLVM: define dso_local void @multiple_non_case
// LLVM: [[SWDEFAULT:.*]]:
// LLVM: call void @action1()
// LLVM: br label %[[L2:.*]]
// LLVM: [[L2]]:
// LLVM: call void @action2()
// LLVM: br label %[[BREAK:.*]]
// OGCG: define dso_local void @multiple_non_case
// OGCG: sw.default:
// OGCG: call void @action1()
@ -213,26 +158,6 @@ extern "C" void case_follow_label(int v) {
// CIR: cir.call @action2()
// CIR: cir.goto "label"
// LLVM: define dso_local void @case_follow_label
// LLVM: switch i32 {{.*}}, label %[[SWDEFAULT:.*]] [
// LLVM: i32 1, label %[[LABEL:.*]]
// LLVM: i32 2, label %[[CASE2:.*]]
// LLVM: ]
// LLVM: [[LABEL]]:
// LLVM: br label %[[CASE2]]
// LLVM: [[CASE2]]:
// LLVM: call void @action1()
// LLVM: br label %[[BREAK:.*]]
// LLVM: [[BREAK]]:
// LLVM: br label %[[END:.*]]
// LLVM: [[SWDEFAULT]]:
// LLVM: call void @action2()
// LLVM: br label %[[LABEL]]
// LLVM: [[END]]:
// LLVM: br label %[[RET:.*]]
// LLVM: [[RET]]:
// LLVM: ret void
// OGCG: define dso_local void @case_follow_label
// OGCG: sw.bb:
// OGCG: br label %label
@ -272,26 +197,6 @@ extern "C" void default_follow_label(int v) {
// CIR: cir.call @action2()
// CIR: cir.goto "label"
// LLVM: define dso_local void @default_follow_label
// LLVM: [[CASE1:.*]]:
// LLVM: br label %[[BB8:.*]]
// LLVM: [[BB8]]:
// LLVM: br label %[[CASE2:.*]]
// LLVM: [[CASE2]]:
// LLVM: call void @action1()
// LLVM: br label %[[BREAK:.*]]
// LLVM: [[LABEL:.*]]:
// LLVM: br label %[[SWDEFAULT:.*]]
// LLVM: [[SWDEFAULT]]:
// LLVM: call void @action2()
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: br label %[[LABEL]]
// LLVM: [[BREAK]]:
// LLVM: br label %[[RET:.*]]
// LLVM: [[RET]]:
// LLVM: ret void
// OGCG: define dso_local void @default_follow_label
// OGCG: sw.bb:
// OGCG: call void @action1()

View File

@ -1,7 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
@ -14,8 +12,8 @@ labelA:
// CIR: cir.label "labelA"
// CIR: cir.return
// LLVM:define dso_local void @label
// LLVM: ret void
// Note: We are not lowering to LLVM IR via CIR at this stage because that
// process depends on the GotoSolver.
// OGCG: define dso_local void @label
// OGCG: br label %labelA
@ -35,11 +33,6 @@ labelC:
// CIR: cir.label "labelC"
// CIR: cir.return
// LLVM: define dso_local void @multiple_labels()
// LLVM: br label %1
// LLVM: 1:
// LLVM: ret void
// OGCG: define dso_local void @multiple_labels
// OGCG: br label %labelB
// OGCG: labelB:
@ -63,22 +56,6 @@ labelD:
// CIR: }
// CIR: cir.return
// LLVM: define dso_local void @label_in_if
// LLVM: br label %3
// LLVM: 3:
// LLVM: [[LOAD:%.*]] = load i32, ptr [[COND:%.*]], align 4
// LLVM: [[CMP:%.*]] = icmp ne i32 [[LOAD]], 0
// LLVM: br i1 [[CMP]], label %6, label %9
// LLVM: 6:
// LLVM: [[LOAD2:%.*]] = load i32, ptr [[COND]], align 4
// LLVM: [[ADD1:%.*]] = add nsw i32 [[LOAD2]], 1
// LLVM: store i32 [[ADD1]], ptr [[COND]], align 4
// LLVM: br label %9
// LLVM: 9:
// LLVM: br label %10
// LLVM: 10:
// LLVM: ret void
// OGCG: define dso_local void @label_in_if
// OGCG: if.then:
// OGCG: br label %labelD
@ -103,13 +80,6 @@ void after_return() {
// CIR: cir.label "label"
// CIR: cir.br ^bb1
// LLVM: define dso_local void @after_return
// LLVM: br label %1
// LLVM: 1:
// LLVM: ret void
// LLVM: 2:
// LLVM: br label %1
// OGCG: define dso_local void @after_return
// OGCG: br label %label
// OGCG: label:
@ -127,11 +97,6 @@ void after_unreachable() {
// CIR: cir.label "label"
// CIR: cir.return
// LLVM: define dso_local void @after_unreachable
// LLVM: unreachable
// LLVM: 1:
// LLVM: ret void
// OGCG: define dso_local void @after_unreachable
// OGCG: unreachable
// OGCG: label:
@ -146,9 +111,6 @@ end:
// CIR: cir.return
// CIR: }
// LLVM: define dso_local void @labelWithoutMatch
// LLVM: ret void
// OGCG: define dso_local void @labelWithoutMatch
// OGCG: br label %end
// OGCG: end:
@ -170,15 +132,6 @@ void foo() {
// CIR: cir.label "label"
// CIR: %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["agg.tmp0"]
// LLVM:define dso_local void @foo() {
// LLVM: [[ALLOC:%.*]] = alloca %struct.S, i64 1, align 1
// LLVM: br label %2
// LLVM:2:
// LLVM: [[CALL:%.*]] = call %struct.S @get()
// LLVM: store %struct.S [[CALL]], ptr [[ALLOC]], align 1
// LLVM: [[LOAD:%.*]] = load %struct.S, ptr [[ALLOC]], align 1
// LLVM: call void @bar(%struct.S [[LOAD]])
// OGCG: define dso_local void @foo()
// OGCG: %agg.tmp = alloca %struct.S, align 1
// OGCG: %undef.agg.tmp = alloca %struct.S, align 1

View File

@ -1,11 +0,0 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cpp.cir
// RUN: FileCheck --check-prefix=CIR-CPP --input-file=%t.cpp.cir %s
// RUN: %clang_cc1 -x c -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.c.cir
// RUN: FileCheck --check-prefix=CIR-C --input-file=%t.c.cir %s
// CIR-CPP: module attributes {{{.*}}cir.lang = #cir.lang<cxx>{{.*}}}
// CIR-C: module attributes {{{.*}}cir.lang = #cir.lang<c>{{.*}}}
int main() {
return 0;
}

View File

@ -1,5 +0,0 @@
// RUN: cir-opt %s -verify-diagnostics
// expected-error@below {{expected ::cir::SourceLanguage to be one of}}
// expected-error@below {{failed to parse CIR_SourceLanguageAttr parameter 'value'}}
module attributes {cir.lang = #cir.lang<dummy>} { }

View File

@ -1,4 +1,4 @@
// RUN: cir-opt %s -verify-diagnostics -split-input-file
// RUN: cir-opt %s -verify-diagnostics
!s8i = !cir.int<s, 8>
!u32i = !cir.int<u, 32>
@ -7,67 +7,3 @@ cir.func @reference_unknown_vtable() {
%0 = cir.vtable.address_point(@some_vtable, address_point = <index = 0, offset = 2>) : !cir.vptr
cir.return
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>
module {
// expected-error @below {{expected !cir.record type result}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !cir.ptr<!rec_anon_struct>
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {}>
module {
// expected-error @below {{expected record type with one or more subtype}}
cir.global external @_ZTV1S = #cir.vtable<{}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>}>
module {
// expected-error @below {{expected constant array subtype}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.ptr<null> : !cir.ptr<!u8i>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u64i = !cir.int<u, 64>
!rec_anon_struct = !cir.record<struct {!cir.array<!u64i x 4>}>
module {
// expected-error @below {{expected GlobalViewAttr or ConstPtrAttr}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.int<1> : !u64i, #cir.int<1> : !u64i, #cir.int<3> : !u64i, #cir.int<4> : !u64i]> : !cir.array<!u64i x 4>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_Q = !cir.record<struct "Q" {!cir.vptr}>
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!rec_S2 = !cir.record<struct "S2" {!rec_Q, !rec_S}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.ptr<!u8i>}>
module {
// expected-error @below {{expected constant array subtype}}
cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.ptr<null> : !cir.ptr<!u8i>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN2S23keyEv(%arg0: !cir.ptr<!rec_S2>)
}

View File

@ -1,12 +0,0 @@
// RUN: cir-opt %s -split-input-file -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s
// Should parse and print C source language attribute.
module attributes {cir.lang = #cir.lang<c>} { }
// CHECK: module attributes {cir.lang = #cir.lang<c>}
// -----
// Should parse and print C++ source language attribute.
module attributes {cir.lang = #cir.lang<cxx>} { }
// CHECK: module attributes {cir.lang = #cir.lang<cxx>}

View File

@ -1,19 +0,0 @@
// RUN: cir-opt %s | FileCheck %s
!rec_Q = !cir.record<struct "Q" {!cir.vptr}>
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!rec_S2 = !cir.record<struct "S2" {!rec_Q, !rec_S}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>
!rec_anon_struct1 = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 3>}>
module {
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !rec_anon_struct {alignment = 8 : i64}
// CHECK: cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !rec_anon_struct {alignment = 8 : i64}
cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.const_array<[#cir.ptr<-8 : i64> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN2S23keyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 3>}> : !rec_anon_struct1 {alignment = 8 : i64}
// CHECK: cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.const_array<[#cir.ptr<-8 : i64> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN2S23keyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 3>}> : !rec_anon_struct1 {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN2S23keyEv(%arg0: !cir.ptr<!rec_S2>)
}

View File

@ -1,52 +0,0 @@
// RUN: cir-opt %s --pass-pipeline='builtin.module(cir-to-llvm,canonicalize{region-simplify=disabled})' -o - | FileCheck %s -check-prefix=MLIR
!s32i = !cir.int<s, 32>
module {
cir.func @gotoFromIf(%arg0: !s32i) -> !s32i {
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
%1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>
cir.scope {
%6 = cir.load %0 : !cir.ptr<!s32i>, !s32i
%7 = cir.const #cir.int<5> : !s32i
%8 = cir.cmp(gt, %6, %7) : !s32i, !cir.bool
cir.if %8 {
cir.goto "err"
}
}
%2 = cir.const #cir.int<0> : !s32i
cir.store %2, %1 : !s32i, !cir.ptr<!s32i>
cir.br ^bb1
^bb1:
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i
cir.return %3 : !s32i
^bb2:
cir.label "err"
%4 = cir.const #cir.int<1> : !s32i
%5 = cir.unary(minus, %4) : !s32i, !s32i
cir.store %5, %1 : !s32i, !cir.ptr<!s32i>
cir.br ^bb1
}
// MLIR: llvm.func @gotoFromIf
// MLIR: %[[#One:]] = llvm.mlir.constant(1 : i32) : i32
// MLIR: %[[#Zero:]] = llvm.mlir.constant(0 : i32) : i32
// MLIR: llvm.cond_br {{.*}}, ^bb[[#COND_YES:]], ^bb[[#COND_NO:]]
// MLIR: ^bb[[#COND_YES]]:
// MLIR: llvm.br ^bb[[#GOTO_BLK:]]
// MLIR: ^bb[[#COND_NO]]:
// MLIR: llvm.br ^bb[[#BLK:]]
// MLIR: ^bb[[#BLK]]:
// MLIR: llvm.store %[[#Zero]], %[[#Ret_val_addr:]] {{.*}}: i32, !llvm.ptr
// MLIR: llvm.br ^bb[[#RETURN:]]
// MLIR: ^bb[[#RETURN]]:
// MLIR: %[[#Ret_val:]] = llvm.load %[[#Ret_val_addr]] {alignment = 4 : i64} : !llvm.ptr -> i32
// MLIR: llvm.return %[[#Ret_val]] : i32
// MLIR: ^bb[[#GOTO_BLK]]:
// MLIR: %[[#Neg_one:]] = llvm.sub %[[#Zero]], %[[#One]] : i32
// MLIR: llvm.store %[[#Neg_one]], %[[#Ret_val_addr]] {{.*}}: i32, !llvm.ptr
// MLIR: llvm.br ^bb[[#RETURN]]
// MLIR: }
}

View File

@ -327,6 +327,7 @@ __m256i test_mm256_cvtepi8_epi16(__m128i a) {
// CHECK: sext <16 x i8> %{{.*}} to <16 x i16>
return _mm256_cvtepi8_epi16(a);
}
TEST_CONSTEXPR(match_v16hi(_mm256_cvtepi8_epi16(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12));
__m256i test_mm256_cvtepi8_epi32(__m128i a) {
@ -335,6 +336,7 @@ __m256i test_mm256_cvtepi8_epi32(__m128i a) {
// CHECK: sext <8 x i8> %{{.*}} to <8 x i32>
return _mm256_cvtepi8_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepi8_epi32(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0, 1, -2, 3, -4));
__m256i test_mm256_cvtepi8_epi64(__m128i a) {
@ -343,6 +345,7 @@ __m256i test_mm256_cvtepi8_epi64(__m128i a) {
// CHECK: sext <4 x i8> %{{.*}} to <4 x i64>
return _mm256_cvtepi8_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi8_epi64(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0));
__m256i test_mm256_cvtepi16_epi32(__m128i a) {
@ -350,6 +353,7 @@ __m256i test_mm256_cvtepi16_epi32(__m128i a) {
// CHECK: sext <8 x i16> %{{.*}} to <8 x i32>
return _mm256_cvtepi16_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepi16_epi32(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), -300, 2, -1, 0, 1, -2, 3, -4));
__m256i test_mm256_cvtepi16_epi64(__m128i a) {
@ -358,6 +362,7 @@ __m256i test_mm256_cvtepi16_epi64(__m128i a) {
// CHECK: sext <4 x i16> %{{.*}} to <4 x i64>
return _mm256_cvtepi16_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi16_epi64(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), -300, 2, -1, 0));
__m256i test_mm256_cvtepi32_epi64(__m128i a) {
@ -365,6 +370,7 @@ __m256i test_mm256_cvtepi32_epi64(__m128i a) {
// CHECK: sext <4 x i32> %{{.*}} to <4 x i64>
return _mm256_cvtepi32_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi32_epi64(_mm_setr_epi32(-70000, 2, -1, 0)), -70000, 2, -1, 0));
__m256i test_mm256_cvtepu8_epi16(__m128i a) {
@ -372,6 +378,7 @@ __m256i test_mm256_cvtepu8_epi16(__m128i a) {
// CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
return _mm256_cvtepu8_epi16(a);
}
TEST_CONSTEXPR(match_v16hi(_mm256_cvtepu8_epi16(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0, 1, 254, 3, 252, 5, 250, 7, 248, 9, 246, 11, 244));
__m256i test_mm256_cvtepu8_epi32(__m128i a) {
@ -380,6 +387,7 @@ __m256i test_mm256_cvtepu8_epi32(__m128i a) {
// CHECK: zext <8 x i8> %{{.*}} to <8 x i32>
return _mm256_cvtepu8_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepu8_epi32(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0, 1, 254, 3, 252));
__m256i test_mm256_cvtepu8_epi64(__m128i a) {
@ -388,6 +396,7 @@ __m256i test_mm256_cvtepu8_epi64(__m128i a) {
// CHECK: zext <4 x i8> %{{.*}} to <4 x i64>
return _mm256_cvtepu8_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu8_epi64(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0));
__m256i test_mm256_cvtepu16_epi32(__m128i a) {
@ -395,6 +404,7 @@ __m256i test_mm256_cvtepu16_epi32(__m128i a) {
// CHECK: zext <8 x i16> {{.*}} to <8 x i32>
return _mm256_cvtepu16_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepu16_epi32(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), 65236, 2, 65535, 0, 1, 65534, 3, 65532));
__m256i test_mm256_cvtepu16_epi64(__m128i a) {
@ -403,6 +413,7 @@ __m256i test_mm256_cvtepu16_epi64(__m128i a) {
// CHECK: zext <4 x i16> %{{.*}} to <4 x i64>
return _mm256_cvtepu16_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu16_epi64(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), 65236, 2, 65535, 0));
__m256i test_mm256_cvtepu32_epi64(__m128i a) {
@ -410,6 +421,7 @@ __m256i test_mm256_cvtepu32_epi64(__m128i a) {
// CHECK: zext <4 x i32> %{{.*}} to <4 x i64>
return _mm256_cvtepu32_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu32_epi64(_mm_setr_epi32(-70000, 2, -1, 0)), 4294897296, 2, 4294967295, 0));
__m128i test0_mm256_extracti128_si256_0(__m256i a) {
@ -1108,28 +1120,24 @@ __m128i test_mm_sllv_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psllv.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_sllv_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_sllv_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 2, -8, 24, 0));
__m256i test_mm256_sllv_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_sllv_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psllv.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_sllv_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_sllv_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 2, -8, 24, -64, 0, 0, 0, 0));
__m128i test_mm_sllv_epi64(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_sllv_epi64
// CHECK: call {{.*}}<2 x i64> @llvm.x86.avx2.psllv.q(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_sllv_epi64(a, b);
}
TEST_CONSTEXPR(match_m128i(_mm_sllv_epi64((__m128i)(__v2di){1, -3}, (__m128i)(__v2di){8, 63}), 256, 0x8000000000000000ULL));
__m256i test_mm256_sllv_epi64(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_sllv_epi64
// CHECK: call {{.*}}<4 x i64> @llvm.x86.avx2.psllv.q.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_sllv_epi64(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_sllv_epi64((__m256i)(__v4di){1, -2, 3, -4}, (__m256i)(__v4di){1, 2, 3, -4}), 2, -8, 24, 0));
__m256i test_mm256_sra_epi16(__m256i a, __m128i b) {
// CHECK-LABEL: test_mm256_sra_epi16
@ -1172,14 +1180,12 @@ __m128i test_mm_srav_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psrav.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_srav_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_srav_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 0, -1, 0, -1));
__m256i test_mm256_srav_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srav_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrav.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_srav_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_srav_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 0, -1, 0, -1, 0, -1, 0, -1));
__m256i test_mm256_srl_epi16(__m256i a, __m128i b) {
// CHECK-LABEL: test_mm256_srl_epi16
@ -1246,28 +1252,24 @@ __m128i test_mm_srlv_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psrlv.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_srlv_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_srlv_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 0, 1073741823, 0, 0));
__m256i test_mm256_srlv_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srlv_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrlv.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_srlv_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_srlv_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 0, 1073741823, 0, 268435455, 0, 1, 0, 7));
__m128i test_mm_srlv_epi64(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_srlv_epi64
// CHECK: call {{.*}}<2 x i64> @llvm.x86.avx2.psrlv.q(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_srlv_epi64(a, b);
}
TEST_CONSTEXPR(match_m128i(_mm_srlv_epi64((__m128i)(__v2di){1, -3}, (__m128i)(__v2di){8, 63}), 0, 1));
__m256i test_mm256_srlv_epi64(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srlv_epi64
// CHECK: call {{.*}}<4 x i64> @llvm.x86.avx2.psrlv.q.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_srlv_epi64(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_srlv_epi64((__m256i)(__v4di){1, -2, 3, -4}, (__m256i)(__v4di){1, 2, 3, -4}), 0, 0x3FFFFFFFFFFFFFFFULL, 0, 0));
__m256i test_mm256_stream_load_si256(__m256i const *a) {
// CHECK-LABEL: test_mm256_stream_load_si256

View File

@ -3,11 +3,6 @@
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion | FileCheck %s
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
#include <immintrin.h>
#include "builtin_test_helpers.h"

Some files were not shown because too many files have changed in this diff Show More