diff --git a/.arcconfig b/.arcconfig index 5d3ebce01d848..9cb88800d30d7 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,5 +1,6 @@ { "phabricator.uri" : "https://reviews.llvm.org/", "repository.callsign" : "G", - "conduit_uri" : "https://reviews.llvm.org/" + "conduit_uri" : "https://reviews.llvm.org/", + "base": "git:HEAD^" } diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 686fb859b1bd5..c1b4ea99066fd 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -11,17 +11,14 @@ jobs: steps: - uses: actions/checkout@v2 with: - # checkout PR head - ref: '${{github.event.pull_request.head.sha}}' - - name: Fetch target branch - run: git fetch --no-tags --prune --depth=1 origin +refs/heads/${{github.base_ref}}:refs/remotes/origin/${{github.base_ref}} + fetch-depth: 2 - name: Get clang-format first run: sudo apt-get install -yqq clang-format-9 - name: Run clang-format for the patch run: | - git diff -U0 --no-color origin/${{github.base_ref}}..HEAD | ./clang/tools/clang-format/clang-format-diff.py -p1 -binary clang-format-9 > ./clang-format.patch + git diff -U0 --no-color ${GITHUB_SHA}^1 ${GITHUB_SHA} -- | ./clang/tools/clang-format/clang-format-diff.py -p1 -binary clang-format-9 > ./clang-format.patch # Add patch with formatting fixes to CI job artifacts - uses: actions/upload-artifact@v1 diff --git a/.github/workflows/gh_pages.yml b/.github/workflows/gh_pages.yml new file mode 100644 index 0000000000000..0400081776e9b --- /dev/null +++ b/.github/workflows/gh_pages.yml @@ -0,0 +1,43 @@ +name: Generate Doxygen documentation + +on: + schedule: + - cron: 0 1 * * * + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: sycl + path: repo + - uses: actions/checkout@v2 + with: + repository: intel/llvm-docs + path: docs + - name: Install deps + run: sudo apt-get install -y doxygen graphviz ssh ninja-build + - name: Build Docs + run: | + mkdir -p $GITHUB_WORKSPACE/build + cd $GITHUB_WORKSPACE/build + python $GITHUB_WORKSPACE/repo/buildbot/configure.py -w $GITHUB_WORKSPACE \ + -s $GITHUB_WORKSPACE/repo -o $GITHUB_WORKSPACE/build -t Release --docs + cmake --build . --target doxygen-sycl + - name: Deploy + env: + SSH_KEY: ${{secrets.ACTIONS_DEPLOY_KEY}} + run: | + mkdir -p ~/.ssh + echo "$SSH_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval "$(ssh-agent -s)" + ssh-add -k ~/.ssh/id_rsa + cd $GITHUB_WORKSPACE/docs + yes | \cp -rf $GITHUB_WORKSPACE/build/tools/sycl/doc/doxygen/html/* . + git config --global user.name "iclsrc" + git config --global user.email "ia.compiler.tools.git@intel.com" + git add . + git diff-index --quiet HEAD || git commit -m "Update docs" -s + git push diff --git a/buildbot/configure.py b/buildbot/configure.py index 9bb1d26ad52f1..c0e4dc3eb6d31 100644 --- a/buildbot/configure.py +++ b/buildbot/configure.py @@ -17,6 +17,7 @@ def do_configure(args): libclc_targets_to_build = '' sycl_build_pi_cuda = 'OFF' llvm_enable_assertions = 'ON' + llvm_enable_doxygen = 'OFF' if platform.system() == 'Linux': icd_loader_lib = os.path.join(icd_loader_lib, "libOpenCL.so") @@ -32,6 +33,9 @@ def do_configure(args): if args.assertions: llvm_enable_assertions = 'ON' + if args.docs: + llvm_enable_doxygen = 'ON' + install_dir = os.path.join(args.obj_dir, "install") cmake_cmd = [ @@ -52,6 +56,7 @@ def do_configure(args): "-DSYCL_ENABLE_WERROR=ON", "-DCMAKE_INSTALL_PREFIX={}".format(install_dir), "-DSYCL_INCLUDE_TESTS=ON", # Explicitly include all kinds of SYCL tests. + "-DLLVM_ENABLE_DOXYGEN={}".format(llvm_enable_doxygen), llvm_dir ] @@ -84,6 +89,7 @@ def main(): metavar="BUILD_TYPE", required=True, help="build type, debug or release") parser.add_argument("--cuda", action='store_true', help="switch from OpenCL to CUDA") parser.add_argument("--assertions", action='store_true', help="build with assertions") + parser.add_argument("--docs", action='store_true', help="build Doxygen documentation") args = parser.parse_args() diff --git a/buildbot/dependency.py b/buildbot/dependency.py index 145a7c18429f1..6f8cede47bb0a 100644 --- a/buildbot/dependency.py +++ b/buildbot/dependency.py @@ -71,6 +71,7 @@ def do_dependency(args): install_dir = os.path.join(args.obj_dir, "install") cmake_cmd = ["cmake", "-G", "Ninja", "-DCMAKE_INSTALL_PREFIX={}".format(install_dir), + "-DOPENCL_ICD_LOADER_HEADERS_DIR={}".format(ocl_header_dir), ".." ] subprocess.check_call(cmake_cmd, cwd=icd_build_dir) diff --git a/clang-tools-extra/.arcconfig b/clang-tools-extra/.arcconfig deleted file mode 100644 index d4a00161bce5b..0000000000000 --- a/clang-tools-extra/.arcconfig +++ /dev/null @@ -1,4 +0,0 @@ -{ - "repository.callsign" : "CTE", - "conduit_uri" : "https://reviews.llvm.org/" -} diff --git a/clang-tools-extra/clang-tidy/add_new_check.py b/clang-tools-extra/clang-tidy/add_new_check.py index 1ef7165a12c9a..22aadd612d708 100755 --- a/clang-tools-extra/clang-tidy/add_new_check.py +++ b/clang-tools-extra/clang-tidy/add_new_check.py @@ -221,7 +221,7 @@ def add_release_notes(module_path, module, check_name): lineMatcher = re.compile('New checks') nextSectionMatcher = re.compile('New check aliases') - checkerMatcher = re.compile('- New :doc:`(.*)') + checkMatcher = re.compile('- New :doc:`(.*)') print('Updating %s...' % filename) with open(filename, 'w') as f: @@ -234,10 +234,10 @@ def add_release_notes(module_path, module, check_name): if not note_added: match = lineMatcher.match(line) match_next = nextSectionMatcher.match(line) - match_checker = checkerMatcher.match(line) - if match_checker: - last_checker = match_checker.group(1) - if last_checker > check_name_dashes: + match_check = checkMatcher.match(line) + if match_check: + last_check = match_check.group(1) + if last_check > check_name_dashes: add_note_here = True if match_next: diff --git a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp index 55d8884484b5b..d562d8c3d213a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp @@ -14,6 +14,8 @@ #include #include +// FixItHint + using namespace clang::ast_matchers; namespace clang { diff --git a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp index cfbd6543e0866..d382501d191e8 100644 --- a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp @@ -204,9 +204,8 @@ void NoRecursionCheck::handleSCC(ArrayRef SCC) { // First of all, call out every stongly connected function. for (CallGraphNode *N : SCC) { - Decl *D = N->getDecl(); - diag(D->getLocation(), "function %0 is within a recursive call chain") - << cast(D); + FunctionDecl *D = N->getDefinition(); + diag(D->getLocation(), "function %0 is within a recursive call chain") << D; } // Now, SCC only tells us about strongly connected function declarations in @@ -228,13 +227,13 @@ void NoRecursionCheck::handleSCC(ArrayRef SCC) { assert(CyclicCallStack.size() >= 2 && "Cycle requires at least 2 frames"); // Which function we decided to be the entry point that lead to the recursion? - Decl *CycleEntryFn = CyclicCallStack.front().Callee->getDecl(); + FunctionDecl *CycleEntryFn = CyclicCallStack.front().Callee->getDefinition(); // And now, for ease of understanding, let's print the call sequence that // forms the cycle in question. diag(CycleEntryFn->getLocation(), "example recursive call chain, starting from function %0", DiagnosticIDs::Note) - << cast(CycleEntryFn); + << CycleEntryFn; for (int CurFrame = 1, NumFrames = CyclicCallStack.size(); CurFrame != NumFrames; ++CurFrame) { CallGraphNode::CallRecord PrevNode = CyclicCallStack[CurFrame - 1]; diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index e3e84b71601b5..90fcf38f83b78 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -18,7 +18,9 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/FormatVariadic.h" #include #include #include @@ -304,6 +306,132 @@ static void transformSubToCanonicalAddExpr(BinaryOperatorKind &Opcode, } } +// to use in the template below +static OverloadedOperatorKind getOp(const BinaryOperator *Op) { + return BinaryOperator::getOverloadedOperator(Op->getOpcode()); +} + +static OverloadedOperatorKind getOp(const CXXOperatorCallExpr *Op) { + if (Op->getNumArgs() != 2) + return OO_None; + return Op->getOperator(); +} + +static std::pair +getOperands(const BinaryOperator *Op) { + return {Op->getLHS()->IgnoreParenImpCasts(), + Op->getRHS()->IgnoreParenImpCasts()}; +} + +static std::pair +getOperands(const CXXOperatorCallExpr *Op) { + return {Op->getArg(0)->IgnoreParenImpCasts(), + Op->getArg(1)->IgnoreParenImpCasts()}; +} + +template +static const TExpr *checkOpKind(const Expr *TheExpr, + OverloadedOperatorKind OpKind) { + const auto *AsTExpr = dyn_cast_or_null(TheExpr); + if (AsTExpr && getOp(AsTExpr) == OpKind) + return AsTExpr; + + return nullptr; +} + +// returns true if a subexpression has two directly equivalent operands and +// is already handled by operands/parametersAreEquivalent +template +static bool collectOperands(const Expr *Part, + SmallVector &AllOperands, + OverloadedOperatorKind OpKind) { + if (const auto *BinOp = checkOpKind(Part, OpKind)) { + const std::pair Operands = getOperands(BinOp); + if (areEquivalentExpr(Operands.first, Operands.second)) + return true; + return collectOperands(Operands.first, AllOperands, OpKind) || + collectOperands(Operands.second, AllOperands, OpKind); + } + + AllOperands.push_back(Part); + return false; +} + +template +static bool hasSameOperatorParent(const Expr *TheExpr, + OverloadedOperatorKind OpKind, + ASTContext &Context) { + // IgnoreParenImpCasts logic in reverse: skip surrounding uninteresting nodes + const DynTypedNodeList Parents = Context.getParents(*TheExpr); + for (ast_type_traits::DynTypedNode DynParent : Parents) { + if (const auto *Parent = DynParent.get()) { + bool Skip = isa(Parent) || isa(Parent) || + isa(Parent) || + isa(Parent); + if (Skip && hasSameOperatorParent(Parent, OpKind, Context)) + return true; + if (checkOpKind(Parent, OpKind)) + return true; + } + } + + return false; +} + +template +static bool +markDuplicateOperands(const TExpr *TheExpr, + ast_matchers::internal::BoundNodesTreeBuilder *Builder, + ASTContext &Context) { + const OverloadedOperatorKind OpKind = getOp(TheExpr); + if (OpKind == OO_None) + return false; + // if there are no nested operators of the same kind, it's handled by + // operands/parametersAreEquivalent + const std::pair Operands = getOperands(TheExpr); + if (!(checkOpKind(Operands.first, OpKind) || + checkOpKind(Operands.second, OpKind))) + return false; + + // if parent is the same kind of operator, it's handled by a previous call to + // markDuplicateOperands + if (hasSameOperatorParent(TheExpr, OpKind, Context)) + return false; + + SmallVector AllOperands; + if (collectOperands(Operands.first, AllOperands, OpKind)) + return false; + if (collectOperands(Operands.second, AllOperands, OpKind)) + return false; + size_t NumOperands = AllOperands.size(); + llvm::SmallBitVector Duplicates(NumOperands); + for (size_t I = 0; I < NumOperands; I++) { + if (Duplicates[I]) + continue; + bool FoundDuplicates = false; + + for (size_t J = I + 1; J < NumOperands; J++) { + if (AllOperands[J]->HasSideEffects(Context)) + break; + + if (areEquivalentExpr(AllOperands[I], AllOperands[J])) { + FoundDuplicates = true; + Duplicates.set(J); + Builder->setBinding( + SmallString<11>(llvm::formatv("duplicate{0}", J)), + ast_type_traits::DynTypedNode::create(*AllOperands[J])); + } + } + + if (FoundDuplicates) + Builder->setBinding( + SmallString<11>(llvm::formatv("duplicate{0}", I)), + ast_type_traits::DynTypedNode::create(*AllOperands[I])); + } + + return Duplicates.any(); +} + AST_MATCHER(Expr, isIntegerConstantExpr) { if (Node.isInstantiationDependent()) return false; @@ -314,6 +442,10 @@ AST_MATCHER(BinaryOperator, operandsAreEquivalent) { return areEquivalentExpr(Node.getLHS(), Node.getRHS()); } +AST_MATCHER(BinaryOperator, nestedOperandsAreEquivalent) { + return markDuplicateOperands(&Node, Builder, Finder->getASTContext()); +} + AST_MATCHER(ConditionalOperator, expressionsAreEquivalent) { return areEquivalentExpr(Node.getTrueExpr(), Node.getFalseExpr()); } @@ -323,6 +455,10 @@ AST_MATCHER(CallExpr, parametersAreEquivalent) { areEquivalentExpr(Node.getArg(0), Node.getArg(1)); } +AST_MATCHER(CXXOperatorCallExpr, nestedParametersAreEquivalent) { + return markDuplicateOperands(&Node, Builder, Finder->getASTContext()); +} + AST_MATCHER(BinaryOperator, binaryOperatorIsInMacro) { return Node.getOperatorLoc().isMacroID(); } @@ -484,8 +620,15 @@ static bool isNonConstReferenceType(QualType ParamType) { // is a temporary expression. Whether the second parameter is checked is // controlled by the parameter `ParamsToCheckCount`. static bool -canOverloadedOperatorArgsBeModified(const FunctionDecl *OperatorDecl, +canOverloadedOperatorArgsBeModified(const CXXOperatorCallExpr *OperatorCall, bool checkSecondParam) { + const auto *OperatorDecl = + dyn_cast_or_null(OperatorCall->getCalleeDecl()); + // if we can't find the declaration, conservatively assume it can modify + // arguments + if (!OperatorDecl) + return true; + unsigned ParamCount = OperatorDecl->getNumParams(); // Overloaded operators declared inside a class have only one param. @@ -527,14 +670,7 @@ static bool retrieveRelationalIntegerConstantExpr( Value = APSInt(32, false); } else if (const auto *OverloadedOperatorExpr = Result.Nodes.getNodeAs(OverloadId)) { - const auto *OverloadedFunctionDecl = dyn_cast_or_null(OverloadedOperatorExpr->getCalleeDecl()); - if (!OverloadedFunctionDecl) - return false; - - if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false)) - return false; - - if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false)) + if (canOverloadedOperatorArgsBeModified(OverloadedOperatorExpr, false)) return false; if (const auto *Arg = OverloadedOperatorExpr->getArg(1)) { @@ -714,6 +850,21 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { .bind("binary"), this); + // Logical or bitwise operator with equivalent nested operands, like (X && Y + // && X) or (X && (Y && X)) + Finder->addMatcher( + binaryOperator(anyOf(hasOperatorName("|"), hasOperatorName("&"), + hasOperatorName("||"), hasOperatorName("&&"), + hasOperatorName("^")), + nestedOperandsAreEquivalent(), + // Filter noisy false positives. + unless(isInTemplateInstantiation()), + unless(binaryOperatorIsInMacro()), + // TODO: if the banned macros are themselves duplicated + unless(hasDescendant(BannedIntegerLiteral))) + .bind("nested-duplicates"), + this); + // Conditional (trenary) operator with equivalent operands, like (Y ? X : X). Finder->addMatcher(conditionalOperator(expressionsAreEquivalent(), // Filter noisy false positives. @@ -740,6 +891,19 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { .bind("call"), this); + // Overloaded operators with equivalent operands. + Finder->addMatcher( + cxxOperatorCallExpr( + anyOf(hasOverloadedOperatorName("|"), hasOverloadedOperatorName("&"), + hasOverloadedOperatorName("||"), + hasOverloadedOperatorName("&&"), + hasOverloadedOperatorName("^")), + nestedParametersAreEquivalent(), argumentCountIs(2), + // Filter noisy false positives. + unless(isMacro()), unless(isInTemplateInstantiation())) + .bind("nested-duplicates"), + this); + // Match expressions like: !(1 | 2 | 3) Finder->addMatcher( implicitCastExpr( @@ -1061,17 +1225,29 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) { } if (const auto *Call = Result.Nodes.getNodeAs("call")) { - const auto *OverloadedFunctionDecl = dyn_cast_or_null(Call->getCalleeDecl()); - if (!OverloadedFunctionDecl) - return; - - if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, true)) + if (canOverloadedOperatorArgsBeModified(Call, true)) return; diag(Call->getOperatorLoc(), "both sides of overloaded operator are equivalent"); } + if (const auto *Op = Result.Nodes.getNodeAs("nested-duplicates")) { + const auto *Call = dyn_cast(Op); + if (Call && canOverloadedOperatorArgsBeModified(Call, true)) + return; + + StringRef Message = + Call ? "overloaded operator has equivalent nested operands" + : "operator has equivalent nested operands"; + + const auto Diag = diag(Op->getExprLoc(), Message); + for (const auto &KeyValue : Result.Nodes.getMap()) { + if (StringRef(KeyValue.first).startswith("duplicate")) + Diag << KeyValue.second.getSourceRange(); + } + } + if (const auto *NegateOperator = Result.Nodes.getNodeAs("logical-bitwise-confusion")) { SourceLocation OperatorLoc = NegateOperator->getOperatorLoc(); diff --git a/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp index 8c87dae90080a..811b55bd12bec 100644 --- a/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp @@ -60,7 +60,12 @@ void UnconventionalAssignOperatorCheck::registerMatchers( anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())), cxxOperatorCallExpr(argumentCountIs(1), callee(unresolvedLookupExpr()), - hasArgument(0, cxxThisExpr()))))))); + hasArgument(0, cxxThisExpr())), + cxxOperatorCallExpr( + hasOverloadedOperatorName("="), + hasArgument( + 0, unaryOperator(hasOperatorName("*"), + hasUnaryOperand(cxxThisExpr()))))))))); const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType); Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign)) diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp index cd094219c50be..e00043841b993 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp @@ -16,12 +16,10 @@ namespace clang { namespace tidy { namespace modernize { -static const llvm::SmallVector DeprecatedTypes = { - {"::std::ios_base::io_state"}, - {"::std::ios_base::open_mode"}, - {"::std::ios_base::seek_dir"}, - {"::std::ios_base::streamoff"}, - {"::std::ios_base::streampos"}}; +static constexpr std::array DeprecatedTypes = { + "::std::ios_base::io_state", "::std::ios_base::open_mode", + "::std::ios_base::seek_dir", "::std::ios_base::streamoff", + "::std::ios_base::streampos"}; static const llvm::StringMap ReplacementTypes = { {"io_state", "iostate"}, diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 0171964b52648..45cf87bccfc32 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -18,6 +18,8 @@ #define DEBUG_TYPE "clang-tidy" +// FixItHint + using namespace clang::ast_matchers; namespace clang { diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp index 78834914a5cc2..2938e2b9c7cd0 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp @@ -61,6 +61,55 @@ formatDereference(const ast_matchers::MatchFinder::MatchResult &Result, return (llvm::Twine("*") + Text).str(); } +// Trying to get CallExpr in which CxxConstructExpr is called. +static const clang::CallExpr * +tryGetCallExprAncestorForCxxConstructExpr(const Expr *TheExpr, + ASTContext &Context) { + // We skip nodes such as CXXBindTemporaryExpr, MaterializeTemporaryExpr. + for (ast_type_traits::DynTypedNode DynParent : Context.getParents(*TheExpr)) { + if (const auto *Parent = DynParent.get()) { + if (const auto *TheCallExpr = dyn_cast(Parent)) + return TheCallExpr; + + if (const clang::CallExpr *TheCallExpr = + tryGetCallExprAncestorForCxxConstructExpr(Parent, Context)) + return TheCallExpr; + } + } + + return nullptr; +} + +// Check that ParamDecl of CallExprDecl has rvalue type. +static bool checkParamDeclOfAncestorCallExprHasRValueRefType( + const Expr *TheCxxConstructExpr, ASTContext &Context) { + if (const clang::CallExpr *TheCallExpr = + tryGetCallExprAncestorForCxxConstructExpr(TheCxxConstructExpr, + Context)) { + for (unsigned i = 0; i < TheCallExpr->getNumArgs(); ++i) { + const Expr *Arg = TheCallExpr->getArg(i); + if (Arg->getSourceRange() == TheCxxConstructExpr->getSourceRange()) { + if (const auto *TheCallExprFuncProto = + TheCallExpr->getCallee() + ->getType() + ->getPointeeType() + ->getAs()) { + if (TheCallExprFuncProto->getParamType(i)->isRValueReferenceType()) + return true; + } + } + } + } + + return false; +} + +AST_MATCHER(CXXConstructExpr, + matchedParamDeclOfAncestorCallExprHasRValueRefType) { + return checkParamDeclOfAncestorCallExprHasRValueRefType( + &Node, Finder->getASTContext()); +} + } // end namespace void RedundantStringCStrCheck::registerMatchers( @@ -95,9 +144,13 @@ void RedundantStringCStrCheck::registerMatchers( .bind("call"); // Detect redundant 'c_str()' calls through a string constructor. - Finder->addMatcher(cxxConstructExpr(StringConstructorExpr, - hasArgument(0, StringCStrCallExpr)), - this); + // If CxxConstructExpr is the part of some CallExpr we need to + // check that matched ParamDecl of the ancestor CallExpr is not rvalue. + Finder->addMatcher( + cxxConstructExpr( + StringConstructorExpr, hasArgument(0, StringCStrCallExpr), + unless(matchedParamDeclOfAncestorCallExprHasRValueRefType())), + this); // Detect: 's == str.c_str()' -> 's == str' Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/rename_check.py b/clang-tools-extra/clang-tidy/rename_check.py index 2dde9734ed54f..528c2a19a2b75 100755 --- a/clang-tools-extra/clang-tidy/rename_check.py +++ b/clang-tools-extra/clang-tidy/rename_check.py @@ -169,21 +169,45 @@ def add_release_notes(clang_tidy_path, old_check_name, new_check_name): with open(filename, 'r') as f: lines = f.readlines() + lineMatcher = re.compile('Renamed checks') + nextSectionMatcher = re.compile('Improvements to include-fixer') + checkMatcher = re.compile('- The \'(.*)') + print('Updating %s...' % filename) with open(filename, 'wb') as f: note_added = False header_found = False + next_header_found = False + add_note_here = False for line in lines: if not note_added: - match = re.search('Renamed checks', line) + match = lineMatcher.match(line) + match_next = nextSectionMatcher.match(line) + match_check = checkMatcher.match(line) + if match_check: + last_check = match_check.group(1) + if last_check > old_check_name: + add_note_here = True + + if match_next: + next_header_found = True + add_note_here = True + if match: header_found = True - elif header_found: + f.write(line) + continue + + if line.startswith('^^^^'): + f.write(line) + continue + + if header_found and add_note_here: if not line.startswith('^^^^'): - f.write(""" -- The '%s' check was renamed to :doc:`%s + f.write("""- The '%s' check was renamed to :doc:`%s ` + """ % (old_check_name, new_check_name, new_check_name)) note_added = True diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index e3eccb50a496c..fc5a07e69e9d6 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -30,7 +30,7 @@ if(CLANG_BUILT_STANDALONE) endif() set(CLANGD_ATOMIC_LIB "") -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) +if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB OR NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) list(APPEND CLANGD_ATOMIC_LIB "atomic") endif() diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 93609a8852db9..c31a0a417ebe9 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -559,6 +559,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, {"codeActionProvider", std::move(CodeActionProvider)}, {"completionProvider", llvm::json::Object{ + {"allCommitCharacters", " \t()[]{}<>:;,+-/*%^&#?.=\"'|"}, {"resolveProvider", false}, // We do extra checks for '>' and ':' in completion to only // trigger on '->' and '::'. diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 48cf921ff18cf..6e37a7b441cb1 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -395,7 +395,9 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName, WorkScheduler.runWithAST("Rename", File, std::move(Action)); } -static llvm::Expected +// May generate several candidate selections, due to SelectionTree ambiguity. +// vector of pointers because GCC doesn't like non-copyable Selection. +static llvm::Expected>> tweakSelection(const Range &Sel, const InputsAndAST &AST) { auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start); if (!Begin) @@ -403,7 +405,16 @@ tweakSelection(const Range &Sel, const InputsAndAST &AST) { auto End = positionToOffset(AST.Inputs.Contents, Sel.end); if (!End) return End.takeError(); - return Tweak::Selection(AST.Inputs.Index, AST.AST, *Begin, *End); + std::vector> Result; + SelectionTree::createEach( + AST.AST.getASTContext(), AST.AST.getTokens(), *Begin, *End, + [&](SelectionTree T) { + Result.push_back(std::make_unique( + AST.Inputs.Index, AST.AST, *Begin, *End, std::move(T))); + return false; + }); + assert(!Result.empty() && "Expected at least one SelectionTree"); + return std::move(Result); } void ClangdServer::enumerateTweaks(PathRef File, Range Sel, @@ -412,12 +423,21 @@ void ClangdServer::enumerateTweaks(PathRef File, Range Sel, this](Expected InpAST) mutable { if (!InpAST) return CB(InpAST.takeError()); - auto Selection = tweakSelection(Sel, *InpAST); - if (!Selection) - return CB(Selection.takeError()); + auto Selections = tweakSelection(Sel, *InpAST); + if (!Selections) + return CB(Selections.takeError()); std::vector Res; - for (auto &T : prepareTweaks(*Selection, TweakFilter)) - Res.push_back({T->id(), T->title(), T->intent()}); + // Don't allow a tweak to fire more than once across ambiguous selections. + llvm::DenseSet PreparedTweaks; + auto Filter = [&](const Tweak &T) { + return TweakFilter(T) && !PreparedTweaks.count(T.id()); + }; + for (const auto &Sel : *Selections) { + for (auto &T : prepareTweaks(*Sel, Filter)) { + Res.push_back({T->id(), T->title(), T->intent()}); + PreparedTweaks.insert(T->id()); + } + } CB(std::move(Res)); }; @@ -432,21 +452,30 @@ void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID, FS = FSProvider.getFileSystem()](Expected InpAST) mutable { if (!InpAST) return CB(InpAST.takeError()); - auto Selection = tweakSelection(Sel, *InpAST); - if (!Selection) - return CB(Selection.takeError()); - auto A = prepareTweak(TweakID, *Selection); - if (!A) - return CB(A.takeError()); - auto Effect = (*A)->apply(*Selection); - if (!Effect) - return CB(Effect.takeError()); - for (auto &It : Effect->ApplyEdits) { - Edit &E = It.second; - format::FormatStyle Style = - getFormatStyleForFile(File, E.InitialCode, FS.get()); - if (llvm::Error Err = reformatEdit(E, Style)) - elog("Failed to format {0}: {1}", It.first(), std::move(Err)); + auto Selections = tweakSelection(Sel, *InpAST); + if (!Selections) + return CB(Selections.takeError()); + llvm::Optional> Effect; + // Try each selection, take the first one that prepare()s. + // If they all fail, Effect will hold get the last error. + for (const auto &Selection : *Selections) { + auto T = prepareTweak(TweakID, *Selection); + if (T) { + Effect = (*T)->apply(*Selection); + break; + } + Effect = T.takeError(); + } + assert(Effect.hasValue() && "Expected at least one selection"); + if (*Effect) { + // Tweaks don't apply clang-format, do that centrally here. + for (auto &It : (*Effect)->ApplyEdits) { + Edit &E = It.second; + format::FormatStyle Style = + getFormatStyleForFile(File, E.InitialCode, FS.get()); + if (llvm::Error Err = reformatEdit(E, Style)) + elog("Failed to format {0}: {1}", It.first(), std::move(Err)); + } } return CB(std::move(*Effect)); }; diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index 5156520e2d078..5964680ccf6f5 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -130,8 +130,11 @@ class ClangdServer { llvm::Optional ResourceDir = llvm::None; /// Time to wait after a new file version before computing diagnostics. - DebouncePolicy UpdateDebounce = - DebouncePolicy::fixed(std::chrono::milliseconds(500)); + DebouncePolicy UpdateDebounce = DebouncePolicy{ + /*Min=*/std::chrono::milliseconds(50), + /*Max=*/std::chrono::milliseconds(500), + /*RebuildRatio=*/1, + }; bool SuggestMissingIncludes = false; diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 685079f0ebe82..4528e2a771648 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -31,6 +31,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" @@ -139,7 +140,14 @@ const Type *getPointeeType(const Type *T) { const NamedDecl *getTemplatePattern(const NamedDecl *D) { if (const CXXRecordDecl *CRD = dyn_cast(D)) { - return CRD->getTemplateInstantiationPattern(); + if (const auto *Result = CRD->getTemplateInstantiationPattern()) + return Result; + // getTemplateInstantiationPattern returns null if the Specialization is + // incomplete (e.g. the type didn't need to be complete), fall back to the + // primary template. + if (CRD->getTemplateSpecializationKind() == TSK_Undeclared) + if (const auto *Spec = dyn_cast(CRD)) + return Spec->getSpecializedTemplate()->getTemplatedDecl(); } else if (const FunctionDecl *FD = dyn_cast(D)) { return FD->getTemplateInstantiationPattern(); } else if (auto *VD = dyn_cast(D)) { diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 750df50c47777..851d742711e5a 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -537,9 +537,12 @@ llvm::Optional getHover(ParsedAST &AST, Position Pos, llvm::consumeError(Offset.takeError()); return llvm::None; } - SelectionTree Selection(AST.getASTContext(), AST.getTokens(), *Offset); + // Editors send the position on the left of the hovered character. + // So our selection tree should be biased right. (Tested with VSCode). + SelectionTree ST = SelectionTree::createRight( + AST.getASTContext(), AST.getTokens(), *Offset, *Offset); std::vector Result; - if (const SelectionTree::Node *N = Selection.commonAncestor()) { + if (const SelectionTree::Node *N = ST.commonAncestor()) { auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias); if (!Decls.empty()) { HI = getHoverContents(Decls.front(), Index); diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 80a11ee003077..a376e5f39e795 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1101,6 +1101,8 @@ struct CompletionItem { /// the client side. float score = 0.f; + // TODO: Add custom commitCharacters for some of the completion items. For + // example, it makes sense to use () only for the functions. // TODO(krasimir): The following optional fields defined by the language // server protocol are unsupported: // diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index 574b7477f23f6..d1438d134e15d 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -142,6 +142,11 @@ void update(SelectionTree::Selection &Result, SelectionTree::Selection New) { Result = SelectionTree::Partial; } +// As well as comments, don't count semicolons as real tokens. +// They're not properly claimed as expr-statement is missing from the AST. +bool shouldIgnore(const syntax::Token &Tok) { + return Tok.kind() == tok::comment || Tok.kind() == tok::semi; +} // SelectionTester can determine whether a range of tokens from the PP-expanded // stream (corresponding to an AST node) is considered selected. @@ -172,9 +177,7 @@ class SelectionTester { }); // Precompute selectedness and offset for selected spelled tokens. for (const syntax::Token *T = SelFirst; T < SelLimit; ++T) { - // As well as comments, don't count semicolons as real tokens. - // They're not properly claimed as expr-statement is missing from the AST. - if (T->kind() == tok::comment || T->kind() == tok::semi) + if (shouldIgnore(*T)) continue; SpelledTokens.emplace_back(); Tok &S = SpelledTokens.back(); @@ -671,24 +674,49 @@ std::string SelectionTree::Node::kind() const { return std::move(OS.str()); } -// Decide which selection emulates a "point" query in between characters. -static std::pair pointBounds(unsigned Offset, FileID FID, - ASTContext &AST) { - StringRef Buf = AST.getSourceManager().getBufferData(FID); - // Edge-cases where the choice is forced. - if (Buf.size() == 0) - return {0, 0}; - if (Offset == 0) - return {0, 1}; - if (Offset == Buf.size()) - return {Offset - 1, Offset}; - // We could choose either this byte or the previous. Usually we prefer the - // character on the right of the cursor (or under a block cursor). - // But if that's whitespace/semicolon, we likely want the token on the left. - auto IsIgnoredChar = [](char C) { return isWhitespace(C) || C == ';'; }; - if (IsIgnoredChar(Buf[Offset]) && !IsIgnoredChar(Buf[Offset - 1])) - return {Offset - 1, Offset}; - return {Offset, Offset + 1}; +// Decide which selections emulate a "point" query in between characters. +// If it's ambiguous (the neighboring characters are selectable tokens), returns +// both possibilities in preference order. +// Always returns at least one range - if no tokens touched, and empty range. +static llvm::SmallVector, 2> +pointBounds(unsigned Offset, const syntax::TokenBuffer &Tokens) { + const auto &SM = Tokens.sourceManager(); + SourceLocation Loc = SM.getComposedLoc(SM.getMainFileID(), Offset); + llvm::SmallVector, 2> Result; + // Prefer right token over left. + for (const syntax::Token &Tok : + llvm::reverse(spelledTokensTouching(Loc, Tokens))) { + if (shouldIgnore(Tok)) + continue; + unsigned Offset = Tokens.sourceManager().getFileOffset(Tok.location()); + Result.emplace_back(Offset, Offset + Tok.length()); + } + if (Result.empty()) + Result.emplace_back(Offset, Offset); + return Result; +} + +bool SelectionTree::createEach(ASTContext &AST, + const syntax::TokenBuffer &Tokens, + unsigned Begin, unsigned End, + llvm::function_ref Func) { + if (Begin != End) + return Func(SelectionTree(AST, Tokens, Begin, End)); + for (std::pair Bounds : pointBounds(Begin, Tokens)) + if (Func(SelectionTree(AST, Tokens, Bounds.first, Bounds.second))) + return true; + return false; +} + +SelectionTree SelectionTree::createRight(ASTContext &AST, + const syntax::TokenBuffer &Tokens, + unsigned int Begin, unsigned int End) { + llvm::Optional Result; + createEach(AST, Tokens, Begin, End, [&](SelectionTree T) { + Result = std::move(T); + return true; + }); + return std::move(*Result); } SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, @@ -698,8 +726,6 @@ SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, // but that's all clangd has needed so far. const SourceManager &SM = AST.getSourceManager(); FileID FID = SM.getMainFileID(); - if (Begin == End) - std::tie(Begin, End) = pointBounds(Begin, FID, AST); PrintPolicy.TerseOutput = true; PrintPolicy.IncludeNewlines = false; @@ -711,10 +737,6 @@ SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, dlog("Built selection tree\n{0}", *this); } -SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, - unsigned Offset) - : SelectionTree(AST, Tokens, Offset, Offset) {} - const Node *SelectionTree::commonAncestor() const { const Node *Ancestor = Root; while (Ancestor->Children.size() == 1 && !Ancestor->Selected) diff --git a/clang-tools-extra/clangd/Selection.h b/clang-tools-extra/clangd/Selection.h index a7050c49be6ba..36196f812db93 100644 --- a/clang-tools-extra/clangd/Selection.h +++ b/clang-tools-extra/clangd/Selection.h @@ -29,6 +29,14 @@ // - we determine which low-level nodes are partly or completely covered // by the selection. // - we expose a tree of the selected nodes and their lexical parents. +// +// Sadly LSP specifies locations as being between characters, and this causes +// some ambiguities we cannot cleanly resolve: +// lhs+rhs // targeting '+' or 'lhs'? +// ^ // in GUI editors, double-clicking 'lhs' yields this position! +// +// The best we can do in these cases is try both, which leads to the awkward +// SelectionTree::createEach() API. //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SELECTION_H @@ -64,16 +72,32 @@ namespace clangd { // point back into the AST it was constructed with. class SelectionTree { public: - // Creates a selection tree at the given byte offset in the main file. - // This is approximately equivalent to a range of one character. - // (Usually, the character to the right of Offset, sometimes to the left). - SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, - unsigned Offset); - // Creates a selection tree for the given range in the main file. - // The range includes bytes [Start, End). - // If Start == End, uses the same heuristics as SelectionTree(AST, Start). - SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, - unsigned Start, unsigned End); + // Create selection trees for the given range, and pass them to Func. + // + // There may be multiple possible selection trees: + // - if the range is empty and borders two tokens, a tree for the right token + // and a tree for the left token will be yielded. + // - Func should return true on success (stop) and false on failure (continue) + // + // Always yields at least one tree. If no tokens are touched, it is empty. + static bool createEach(ASTContext &AST, const syntax::TokenBuffer &Tokens, + unsigned Begin, unsigned End, + llvm::function_ref Func); + + // Create a selection tree for the given range. + // + // Where ambiguous (range is empty and borders two tokens), prefer the token + // on the right. + static SelectionTree createRight(ASTContext &AST, + const syntax::TokenBuffer &Tokens, + unsigned Begin, unsigned End); + + // Copies are no good - contain pointers to other nodes. + SelectionTree(const SelectionTree &) = delete; + SelectionTree &operator=(const SelectionTree &) = delete; + // Moves are OK though - internal storage is pointer-stable when moved. + SelectionTree(SelectionTree &&) = default; + SelectionTree &operator=(SelectionTree &&) = default; // Describes to what extent an AST node is covered by the selection. enum Selection : unsigned char { @@ -121,6 +145,11 @@ class SelectionTree { const Node &root() const { return *Root; } private: + // Creates a selection tree for the given range in the main file. + // The range includes bytes [Start, End). + SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, + unsigned Start, unsigned End); + std::deque Nodes; // Stable-pointer storage. const Node *Root; clang::PrintingPolicy PrintPolicy; diff --git a/clang-tools-extra/clangd/SemanticSelection.cpp b/clang-tools-extra/clangd/SemanticSelection.cpp index cbbf31f1b05b5..49fc7703db057 100644 --- a/clang-tools-extra/clangd/SemanticSelection.cpp +++ b/clang-tools-extra/clangd/SemanticSelection.cpp @@ -39,7 +39,8 @@ llvm::Expected> getSemanticRanges(ParsedAST &AST, } // Get node under the cursor. - SelectionTree ST(AST.getASTContext(), AST.getTokens(), *Offset); + SelectionTree ST = SelectionTree::createRight( + AST.getASTContext(), AST.getTokens(), *Offset, *Offset); for (const auto *Node = ST.commonAncestor(); Node != nullptr; Node = Node->Parent) { if (const Decl *D = Node->ASTNode.get()) { diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 61dff3e99cae0..3e0c9f79fc578 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -36,6 +36,7 @@ #include "clang/Index/IndexingAction.h" #include "clang/Index/IndexingOptions.h" #include "clang/Index/USRGeneration.h" +#include "clang/Tooling/Syntax/Tokens.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" @@ -134,15 +135,16 @@ SymbolLocation getPreferredLocation(const Location &ASTLoc, std::vector getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations) { - FileID FID; - unsigned Offset; - std::tie(FID, Offset) = AST.getSourceManager().getDecomposedSpellingLoc(Pos); - SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset); + unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second; std::vector Result; - if (const SelectionTree::Node *N = Selection.commonAncestor()) { - auto Decls = targetDecl(N->ASTNode, Relations); - Result.assign(Decls.begin(), Decls.end()); - } + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, + Offset, [&](SelectionTree ST) { + if (const SelectionTree::Node *N = + ST.commonAncestor()) + llvm::copy(targetDecl(N->ASTNode, Relations), + std::back_inserter(Result)); + return !Result.empty(); + }); return Result; } @@ -592,22 +594,23 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) { // FIXME(nridge): Reduce duplication between this function and declToSym(). static llvm::Optional -declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) { +declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND, + const syntax::TokenBuffer &TB) { auto &SM = Ctx.getSourceManager(); - SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager()); - // getFileLoc is a good choice for us, but we also need to make sure - // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of - // that to make sure it does not switch files. - // FIXME: sourceLocToPosition should not switch files! - SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc())); - SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc())); - if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid()) + auto FilePath = + getCanonicalPath(SM.getFileEntryForID(SM.getFileID(NameLoc)), SM); + auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); + if (!FilePath || !TUPath) + return llvm::None; // Not useful without a uri. + + auto DeclToks = TB.spelledForExpanded(TB.expandedTokens(ND.getSourceRange())); + if (!DeclToks || DeclToks->empty()) return llvm::None; - Position NameBegin = sourceLocToPosition(SM, NameLoc); - Position NameEnd = sourceLocToPosition( - SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts())); + auto NameToks = TB.spelledForExpanded(TB.expandedTokens(NameLoc)); + if (!NameToks || NameToks->empty()) + return llvm::None; index::SymbolInfo SymInfo = index::getSymbolInfo(&ND); // FIXME: this is not classifying constructors, destructors and operators @@ -618,20 +621,18 @@ declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) { THI.name = printName(Ctx, ND); THI.kind = SK; THI.deprecated = ND.isDeprecated(); - THI.range = - Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)}; - THI.selectionRange = Range{NameBegin, NameEnd}; + THI.range = halfOpenToRange( + SM, syntax::Token::range(SM, DeclToks->front(), DeclToks->back()) + .toCharRange(SM)); + THI.selectionRange = halfOpenToRange( + SM, syntax::Token::range(SM, NameToks->front(), NameToks->back()) + .toCharRange(SM)); if (!THI.range.contains(THI.selectionRange)) { // 'selectionRange' must be contained in 'range', so in cases where clang // reports unrelated ranges we need to reconcile somehow. THI.range = THI.selectionRange; } - auto FilePath = - getCanonicalPath(SM.getFileEntryForID(SM.getFileID(BeginLoc)), SM); - auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); - if (!FilePath || !TUPath) - return llvm::None; // Not useful without a uri. THI.uri = URIForFile::canonicalize(*FilePath, *TUPath); return THI; @@ -684,7 +685,8 @@ using RecursionProtectionSet = llvm::SmallSet; static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, std::vector &SuperTypes, - RecursionProtectionSet &RPSet) { + RecursionProtectionSet &RPSet, + const syntax::TokenBuffer &TB) { // typeParents() will replace dependent template specializations // with their class template, so to avoid infinite recursion for // certain types of hierarchies, keep the templates encountered @@ -699,9 +701,9 @@ static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { if (Optional ParentSym = - declToTypeHierarchyItem(ASTCtx, *ParentDecl)) { + declToTypeHierarchyItem(ASTCtx, *ParentDecl, TB)) { ParentSym->parents.emplace(); - fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); + fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet, TB); SuperTypes.emplace_back(std::move(*ParentSym)); } } @@ -712,41 +714,50 @@ static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, } const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { - const SourceManager &SM = AST.getSourceManager(); - SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation( - getBeginningOfIdentifier(Pos, SM, AST.getLangOpts())); - unsigned Offset = - AST.getSourceManager().getDecomposedSpellingLoc(SourceLocationBeg).second; - SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset); - const SelectionTree::Node *N = Selection.commonAncestor(); - if (!N) - return nullptr; - - // Note: explicitReferenceTargets() will search for both template - // instantiations and template patterns, and prefer the former if available - // (generally, one will be available for non-dependent specializations of a - // class template). - auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying); - if (Decls.empty()) - return nullptr; + auto RecordFromNode = + [](const SelectionTree::Node *N) -> const CXXRecordDecl * { + if (!N) + return nullptr; + + // Note: explicitReferenceTargets() will search for both template + // instantiations and template patterns, and prefer the former if available + // (generally, one will be available for non-dependent specializations of a + // class template). + auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying); + if (Decls.empty()) + return nullptr; + + const NamedDecl *D = Decls[0]; + + if (const VarDecl *VD = dyn_cast(D)) { + // If this is a variable, use the type of the variable. + return VD->getType().getTypePtr()->getAsCXXRecordDecl(); + } - const NamedDecl *D = Decls[0]; + if (const CXXMethodDecl *Method = dyn_cast(D)) { + // If this is a method, use the type of the class. + return Method->getParent(); + } - if (const VarDecl *VD = dyn_cast(D)) { - // If this is a variable, use the type of the variable. - return VD->getType().getTypePtr()->getAsCXXRecordDecl(); - } + // We don't handle FieldDecl because it's not clear what behaviour + // the user would expect: the enclosing class type (as with a + // method), or the field's type (as with a variable). - if (const CXXMethodDecl *Method = dyn_cast(D)) { - // If this is a method, use the type of the class. - return Method->getParent(); - } + return dyn_cast(D); + }; - // We don't handle FieldDecl because it's not clear what behaviour - // the user would expect: the enclosing class type (as with a - // method), or the field's type (as with a variable). + const SourceManager &SM = AST.getSourceManager(); + SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation( + getBeginningOfIdentifier(Pos, SM, AST.getLangOpts())); + unsigned Offset = SM.getDecomposedSpellingLoc(SourceLocationBeg).second; + const CXXRecordDecl *Result = nullptr; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset, + Offset, [&](SelectionTree ST) { + Result = RecordFromNode(ST.commonAncestor()); + return Result != nullptr; + }); + return Result; - return dyn_cast(D); } std::vector typeParents(const CXXRecordDecl *CXXRD) { @@ -795,7 +806,7 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, return llvm::None; Optional Result = - declToTypeHierarchyItem(AST.getASTContext(), *CXXRD); + declToTypeHierarchyItem(AST.getASTContext(), *CXXRD, AST.getTokens()); if (!Result) return Result; @@ -804,7 +815,8 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, Result->parents.emplace(); RecursionProtectionSet RPSet; - fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); + fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet, + AST.getTokens()); } if ((Direction == TypeHierarchyDirection::Children || diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index c5dd09b995087..91436431ba09d 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -81,7 +81,8 @@ llvm::DenseSet locateDeclAt(ParsedAST &AST, unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(TokenStartLoc).second; - SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset); + SelectionTree Selection = SelectionTree::createRight( + AST.getASTContext(), AST.getTokens(), Offset, Offset); const SelectionTree::Node *SelectedNode = Selection.commonAncestor(); if (!SelectedNode) return {}; @@ -184,13 +185,6 @@ llvm::Optional renameable(const NamedDecl &RenameDecl, if (!Index) return ReasonToReject::NoIndexProvided; - // Blacklist symbols that are not supported yet in cross-file mode due to the - // limitations of our index. - // FIXME: Renaming templates requires to rename all related specializations, - // our index doesn't have this information. - if (RenameDecl.getDescribedTemplate()) - return ReasonToReject::UnsupportedSymbol; - // FIXME: Renaming virtual methods requires to rename all overridens in // subclasses, our index doesn't have this information. // Note: Within-file rename does support this through the AST. diff --git a/clang-tools-extra/clangd/refactor/Tweak.cpp b/clang-tools-extra/clangd/refactor/Tweak.cpp index 435c36e91efa3..3e3033ce5c7a5 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.cpp +++ b/clang-tools-extra/clangd/refactor/Tweak.cpp @@ -46,10 +46,10 @@ void validateRegistry() { } // namespace Tweak::Selection::Selection(const SymbolIndex *Index, ParsedAST &AST, - unsigned RangeBegin, unsigned RangeEnd) + unsigned RangeBegin, unsigned RangeEnd, + SelectionTree ASTSelection) : Index(Index), AST(&AST), SelectionBegin(RangeBegin), - SelectionEnd(RangeEnd), - ASTSelection(AST.getASTContext(), AST.getTokens(), RangeBegin, RangeEnd) { + SelectionEnd(RangeEnd), ASTSelection(std::move(ASTSelection)) { auto &SM = AST.getSourceManager(); Code = SM.getBufferData(SM.getMainFileID()); Cursor = SM.getComposedLoc(SM.getMainFileID(), RangeBegin); diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h index ca4d43dfa0cc4..84d3bdb3fc0a0 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.h +++ b/clang-tools-extra/clangd/refactor/Tweak.h @@ -48,7 +48,7 @@ class Tweak { /// Input to prepare and apply tweaks. struct Selection { Selection(const SymbolIndex *Index, ParsedAST &AST, unsigned RangeBegin, - unsigned RangeEnd); + unsigned RangeEnd, SelectionTree ASTSelection); /// The text of the active document. llvm::StringRef Code; /// The Index for handling codebase related queries. diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp index 83bc901a3f2f7..cf38227c29d7e 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp @@ -450,6 +450,10 @@ bool ExtractVariable::prepare(const Selection &Inputs) { if (Inputs.SelectionBegin == Inputs.SelectionEnd) return false; const ASTContext &Ctx = Inputs.AST->getASTContext(); + // FIXME: Enable non-C++ cases once we start spelling types explicitly instead + // of making use of auto. + if (!Ctx.getLangOpts().CPlusPlus) + return false; const SourceManager &SM = Inputs.AST->getSourceManager(); if (const SelectionTree::Node *N = computeExtractedExpr(Inputs.ASTSelection.commonAncestor())) diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test index e5ec9fb3d7ac2..68e3ebc24a214 100644 --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -7,6 +7,7 @@ # CHECK-NEXT: "capabilities": { # CHECK-NEXT: "codeActionProvider": true, # CHECK-NEXT: "completionProvider": { +# CHECK-NEXT: "allCommitCharacters": " \t()[]{}<>:;,+-/*%^&#?.=\"'|", # CHECK-NEXT: "resolveProvider": false, # CHECK-NEXT: "triggerCharacters": [ # CHECK-NEXT: ".", diff --git a/clang-tools-extra/clangd/test/type-hierarchy.test b/clang-tools-extra/clangd/test/type-hierarchy.test index 272fb71f3ab82..69014fab4ab1c 100644 --- a/clang-tools-extra/clangd/test/type-hierarchy.test +++ b/clang-tools-extra/clangd/test/type-hierarchy.test @@ -48,7 +48,7 @@ # CHECK-NEXT: "parents": [], # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 15, +# CHECK-NEXT: "character": 16, # CHECK-NEXT: "line": 0 # CHECK-NEXT: }, # CHECK-NEXT: "start": { @@ -71,7 +71,7 @@ # CHECK-NEXT: ], # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 24, +# CHECK-NEXT: "character": 25, # CHECK-NEXT: "line": 1 # CHECK-NEXT: }, # CHECK-NEXT: "start": { @@ -94,7 +94,7 @@ # CHECK-NEXT: ], # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 24, +# CHECK-NEXT: "character": 25, # CHECK-NEXT: "line": 2 # CHECK-NEXT: }, # CHECK-NEXT: "start": { diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index fa091b2a25036..c38ccc3f9441d 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -76,8 +76,8 @@ class TargetDeclTest : public ::testing::Test { TU.ExtraArgs = Flags; auto AST = TU.build(); llvm::Annotations::Range R = A.range(); - SelectionTree Selection(AST.getASTContext(), AST.getTokens(), R.Begin, - R.End); + auto Selection = SelectionTree::createRight( + AST.getASTContext(), AST.getTokens(), R.Begin, R.End); const SelectionTree::Node *N = Selection.commonAncestor(); if (!N) { ADD_FAILURE() << "No node selected!\n" << Code; @@ -309,6 +309,16 @@ TEST_F(TargetDeclTest, ClassTemplate) { {"template<> class Foo<42>", Rel::TemplateInstantiation}, {"class Foo", Rel::TemplatePattern}); + Code = R"cpp( + template class Foo {}; + // The "Foo" SpecializationDecl is incomplete, there is no + // instantiation happening. + void func([[Foo]] *); + )cpp"; + EXPECT_DECLS("TemplateSpecializationTypeLoc", + {"class Foo", Rel::TemplatePattern}, + {"template<> class Foo", Rel::TemplateInstantiation}); + Code = R"cpp( // Explicit specialization. template class Foo{}; diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 503b4d2afa42a..e4de8af93e9ec 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -654,7 +654,7 @@ TEST(Hover, NoHover) { } )cpp", R"cpp(// Template auto parameter. Nothing (Not useful). - template<^auto T> + template void func() { } void foo() { diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp index 3561ff6438f77..82930eb3e0ce8 100644 --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -202,6 +202,13 @@ TEST(RenameTest, WithinFileRename) { } )cpp", + // Incomplete class specializations + R"cpp( + template + class [[Fo^o]] {}; + void func([[Foo]]); + )cpp", + // Template class instantiations. R"cpp( template @@ -887,6 +894,23 @@ TEST(CrossFileRenameTests, WithUpToDateIndex) { } )cpp", }, + { + // class templates. + R"cpp( + template + class [[Foo]] {}; + // FIXME: explicit template specilizations are not supported due the + // clangd index limitations. + template <> + class Foo {}; + )cpp", + R"cpp( + #include "foo.h" + void func() { + [[F^oo]] foo; + } + )cpp", + }, { // class methods. R"cpp( diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index c74ce4426fd06..cf19e07f0b1a7 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -19,20 +19,26 @@ namespace clangd { namespace { using ::testing::UnorderedElementsAreArray; +// Create a selection tree corresponding to a point or pair of points. +// This uses the precisely-defined createRight semantics. The fuzzier +// createEach is tested separately. SelectionTree makeSelectionTree(const StringRef MarkedCode, ParsedAST &AST) { Annotations Test(MarkedCode); switch (Test.points().size()) { - case 1: // Point selection. - return SelectionTree(AST.getASTContext(), AST.getTokens(), - cantFail(positionToOffset(Test.code(), Test.point()))); + case 1: { // Point selection. + unsigned Offset = cantFail(positionToOffset(Test.code(), Test.point())); + return SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), + Offset, Offset); + } case 2: // Range selection. - return SelectionTree( + return SelectionTree::createRight( AST.getASTContext(), AST.getTokens(), cantFail(positionToOffset(Test.code(), Test.points()[0])), cantFail(positionToOffset(Test.code(), Test.points()[1]))); default: ADD_FAILURE() << "Expected 1-2 points for selection.\n" << MarkedCode; - return SelectionTree(AST.getASTContext(), AST.getTokens(), 0u, 0u); + return SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), 0u, + 0u); } } @@ -554,6 +560,61 @@ TEST(SelectionTest, Implicit) { EXPECT_EQ("CXXConstructExpr", nodeKind(&Str->outerImplicit())); } +TEST(SelectionTest, CreateAll) { + llvm::Annotations Test("int$unique^ a=1$ambiguous^+1; $empty^"); + auto AST = TestTU::withCode(Test.code()).build(); + unsigned Seen = 0; + SelectionTree::createEach( + AST.getASTContext(), AST.getTokens(), Test.point("ambiguous"), + Test.point("ambiguous"), [&](SelectionTree T) { + // Expect to see the right-biased tree first. + if (Seen == 0) + EXPECT_EQ("BinaryOperator", nodeKind(T.commonAncestor())); + else if (Seen == 1) + EXPECT_EQ("IntegerLiteral", nodeKind(T.commonAncestor())); + ++Seen; + return false; + }); + EXPECT_EQ(2u, Seen); + + Seen = 0; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), + Test.point("ambiguous"), Test.point("ambiguous"), + [&](SelectionTree T) { + ++Seen; + return true; + }); + EXPECT_EQ(1u, Seen) << "Return true --> stop iterating"; + + Seen = 0; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), + Test.point("unique"), Test.point("unique"), + [&](SelectionTree T) { + ++Seen; + return false; + }); + EXPECT_EQ(1u, Seen) << "no ambiguity --> only one tree"; + + Seen = 0; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), + Test.point("empty"), Test.point("empty"), + [&](SelectionTree T) { + EXPECT_FALSE(T.commonAncestor()); + ++Seen; + return false; + }); + EXPECT_EQ(1u, Seen) << "empty tree still created"; + + Seen = 0; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), + Test.point("unique"), Test.point("ambiguous"), + [&](SelectionTree T) { + ++Seen; + return false; + }); + EXPECT_EQ(1u, Seen) << "one tree for nontrivial selection"; +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/TweakTesting.cpp b/clang-tools-extra/clangd/unittests/TweakTesting.cpp index 33779f4f14072..bbb1af46f93cb 100644 --- a/clang-tools-extra/clangd/unittests/TweakTesting.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTesting.cpp @@ -63,12 +63,33 @@ std::pair rangeOrPoint(const Annotations &A) { cantFail(positionToOffset(A.code(), SelectionRng.end))}; } +// Prepare and apply the specified tweak based on the selection in Input. +// Returns None if and only if prepare() failed. +llvm::Optional> +applyTweak(ParsedAST &AST, const Annotations &Input, StringRef TweakID, + const SymbolIndex *Index) { + auto Range = rangeOrPoint(Input); + llvm::Optional> Result; + SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Range.first, + Range.second, [&](SelectionTree ST) { + Tweak::Selection S(Index, AST, Range.first, + Range.second, std::move(ST)); + if (auto T = prepareTweak(TweakID, S)) { + Result = (*T)->apply(S); + return true; + } else { + llvm::consumeError(T.takeError()); + return false; + } + }); + return Result; +} + MATCHER_P7(TweakIsAvailable, TweakID, Ctx, Header, ExtraArgs, ExtraFiles, Index, FileName, (TweakID + (negation ? " is unavailable" : " is available")).str()) { std::string WrappedCode = wrap(Ctx, arg); Annotations Input(WrappedCode); - auto Selection = rangeOrPoint(Input); TestTU TU; TU.Filename = std::string(FileName); TU.HeaderCode = Header; @@ -76,12 +97,11 @@ MATCHER_P7(TweakIsAvailable, TweakID, Ctx, Header, ExtraArgs, ExtraFiles, Index, TU.ExtraArgs = ExtraArgs; TU.AdditionalFiles = std::move(ExtraFiles); ParsedAST AST = TU.build(); - Tweak::Selection S(Index, AST, Selection.first, Selection.second); - auto PrepareResult = prepareTweak(TweakID, S); - if (PrepareResult) - return true; - llvm::consumeError(PrepareResult.takeError()); - return false; + auto Result = applyTweak(AST, Input, TweakID, Index); + // We only care if prepare() succeeded, but must handle Errors. + if (Result && !*Result) + consumeError(Result->takeError()); + return Result.hasValue(); } } // namespace @@ -90,8 +110,6 @@ std::string TweakTest::apply(llvm::StringRef MarkedCode, llvm::StringMap *EditedFiles) const { std::string WrappedCode = wrap(Context, MarkedCode); Annotations Input(WrappedCode); - auto Selection = rangeOrPoint(Input); - TestTU TU; TU.Filename = std::string(FileName); TU.HeaderCode = Header; @@ -99,23 +117,20 @@ std::string TweakTest::apply(llvm::StringRef MarkedCode, TU.Code = std::string(Input.code()); TU.ExtraArgs = ExtraArgs; ParsedAST AST = TU.build(); - Tweak::Selection S(Index.get(), AST, Selection.first, Selection.second); - auto T = prepareTweak(TweakID, S); - if (!T) { - llvm::consumeError(T.takeError()); - return "unavailable"; - } - llvm::Expected Result = (*T)->apply(S); + auto Result = applyTweak(AST, Input, TweakID, Index.get()); if (!Result) - return "fail: " + llvm::toString(Result.takeError()); - if (Result->ShowMessage) - return "message:\n" + *Result->ShowMessage; - if (Result->ApplyEdits.empty()) + return "unavailable"; + if (!*Result) + return "fail: " + llvm::toString(Result->takeError()); + const auto &Effect = **Result; + if ((*Result)->ShowMessage) + return "message:\n" + *Effect.ShowMessage; + if (Effect.ApplyEdits.empty()) return "no effect"; std::string EditedMainFile; - for (auto &It : Result->ApplyEdits) { + for (auto &It : Effect.ApplyEdits) { auto NewText = It.second.apply(); if (!NewText) return "bad edits: " + llvm::toString(NewText.takeError()); diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp index 68f87a71daf55..24210aaa101d4 100644 --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -230,6 +230,14 @@ TEST_F(ExtractVariableTest, Test) { )cpp"; EXPECT_AVAILABLE(AvailableCases); + ExtraArgs = {"-xc"}; + const char *AvailableButC = R"cpp( + void foo() { + int x = [[1]]; + })cpp"; + EXPECT_UNAVAILABLE(AvailableButC); + ExtraArgs = {}; + const char *NoCrashCases = R"cpp( // error-ok: broken code, but shouldn't crash template @@ -1966,7 +1974,7 @@ TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) { // Basic check for function body and signature. EXPECT_AVAILABLE(R"cpp( class Bar { - [[void [[f^o^o]]() [[{ return; }]]]] + [[void [[f^o^o^]]() [[{ return; }]]]] }; void foo(); diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index 226213979b8b7..27b717b0e1c24 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -943,6 +943,23 @@ TEST(FindReferences, WithinAST) { int x = [[MACRO]]([[MACRO]](1)); } )cpp", + + R"cpp( + int [[v^ar]] = 0; + void foo(int s = [[var]]); + )cpp", + + R"cpp( + template + class [[Fo^o]] {}; + void func([[Foo]]); + )cpp", + + R"cpp( + template + class [[Foo]] {}; + void func([[Fo^o]]); + )cpp", }; for (const char *Test : Tests) { Annotations T(Test); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index dd30f66778a37..0350962c5c862 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -128,7 +128,6 @@ Changes in existing checks Renamed checks ^^^^^^^^^^^^^^ - Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index ce4b20f8693f0..3b9d12ec56ad5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -72,6 +72,7 @@ Clang-Tidy Checks `bugprone-not-null-terminated-result `_, "Yes" `bugprone-parent-virtual-call `_, "Yes" `bugprone-posix-return `_, "Yes" + `bugprone-reserved-identifier `_, "Yes" `bugprone-signed-char-misuse `_, `bugprone-sizeof-container `_, `bugprone-sizeof-expression `_, @@ -189,7 +190,7 @@ Clang-Tidy Checks `misc-definitions-in-headers `_, "Yes" `misc-misplaced-const `_, `misc-new-delete-overloads `_, - `misc-no-recursion `_, + `misc-no-recursion `_, `misc-non-copyable-objects `_, `misc-non-private-member-variables-in-classes `_, `misc-redundant-expression `_, "Yes" @@ -299,6 +300,8 @@ Clang-Tidy Checks `cert-dcl03-c `_, `misc-static-assert `_, "Yes" `cert-dcl16-c `_, `readability-uppercase-literal-suffix `_, "Yes" + `cert-dcl37-c `_, `bugprone-reserved-identifier `_, "Yes" + `cert-dcl51-cpp `_, `bugprone-reserved-identifier `_, "Yes" `cert-dcl54-cpp `_, `misc-new-delete-overloads `_, `cert-dcl59-cpp `_, `google-build-namespaces `_, `cert-err09-cpp `_, `misc-throw-by-value-catch-by-reference `_, diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp index 0cfacfe80cbe0..e323c8a36a2b5 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp @@ -60,12 +60,12 @@ void indirect_recursion() { conditionally_executed(); } +// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'indirect_recursion' +// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here: +// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here: +// CHECK-NOTES: :[[@LINE-11]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles // CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'indirect_recursion' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-12]]:6: note: example recursive call chain, starting from function 'indirect_recursion' -// CHECK-NOTES: :[[@LINE-6]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here: -// CHECK-NOTES: :[[@LINE-11]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here: -// CHECK-NOTES: :[[@LINE-12]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles void taint(); void maybe_selfrecursion_with_two_backedges() { @@ -97,13 +97,13 @@ void indirect_recursion_with_alternatives() { conditionally_executed_choice_1(); } -// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-18]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives' -// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here: -// CHECK-NOTES: :[[@LINE-17]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here: -// CHECK-NOTES: :[[@LINE-18]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles -// CHECK-NOTES: :[[@LINE-17]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-15]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-8]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives' +// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here: +// CHECK-NOTES: :[[@LINE-16]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here: +// CHECK-NOTES: :[[@LINE-17]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles +// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-13]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion] static void indirect_recursion_with_depth2(); static void conditionally_executed_depth1() { @@ -119,14 +119,14 @@ void indirect_recursion_with_depth2() { conditionally_executed_depth0(); } -// CHECK-NOTES: :[[@LINE-14]]:13: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-14]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-11]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0' -// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here: -// CHECK-NOTES: :[[@LINE-15]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here: -// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here: -// CHECK-NOTES: :[[@LINE-9]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles -// CHECK-NOTES: :[[@LINE-16]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-10]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0' +// CHECK-NOTES: :[[@LINE-9]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here: +// CHECK-NOTES: :[[@LINE-14]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here: +// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here: +// CHECK-NOTES: :[[@LINE-8]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles +// CHECK-NOTES: :[[@LINE-15]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-12]]:6: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion] int boo(); void foo(int x = boo()) {} @@ -139,12 +139,12 @@ int boo() { return 0; } -// CHECK-NOTES: :[[@LINE-11]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion] -// CHECK-NOTES: :[[@LINE-13]]:5: note: example recursive call chain, starting from function 'boo' -// CHECK-NOTES: :[[@LINE-7]]:3: note: Frame #1: function 'boo' calls function 'bar' here: -// CHECK-NOTES: :[[@LINE-14]]:18: note: Frame #2: function 'bar' calls function 'boo' here: -// CHECK-NOTES: :[[@LINE-15]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles +// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion] +// CHECK-NOTES: :[[@LINE-6]]:5: note: example recursive call chain, starting from function 'boo' +// CHECK-NOTES: :[[@LINE-6]]:3: note: Frame #1: function 'boo' calls function 'bar' here: +// CHECK-NOTES: :[[@LINE-13]]:18: note: Frame #2: function 'bar' calls function 'boo' here: +// CHECK-NOTES: :[[@LINE-14]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles +// CHECK-NOTES: :[[@LINE-10]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion] int recursion_through_function_ptr() { auto *ptr = &recursion_through_function_ptr; diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-redundant-expression.cpp index 500478159a42e..4a4304be9bf47 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc-redundant-expression.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc-redundant-expression.cpp @@ -81,6 +81,13 @@ int TestSimpleEquivalent(int X, int Y) { if (P2.a[P1.x + 2] < P2.x && P2.a[(P1.x) + (2)] < (P2.x)) return 1; // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: both sides of operator are equivalent + if (X && Y && X) return 1; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: operator has equivalent nested operands + if (X || (Y || X)) return 1; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator has equivalent nested operands + if ((X ^ Y) ^ (Y ^ X)) return 1; + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: operator has equivalent nested operands + return 0; } @@ -106,6 +113,7 @@ int Valid(int X, int Y) { if (++X != ++X) return 1; if (P.a[X]++ != P.a[X]++) return 1; if (P.a[X++] != P.a[X++]) return 1; + if (X && X++ && X) return 1; if ("abc" == "ABC") return 1; if (foo(bar(0)) < (foo(bat(0, 1)))) return 1; @@ -163,6 +171,15 @@ bool operator<(const MyStruct& lhs, const MyStruct& rhs) { return lhs.x < rhs.x; bool operator>(const MyStruct& lhs, MyStruct& rhs) { rhs.x--; return lhs.x > rhs.x; } bool operator||(MyStruct& lhs, const MyStruct& rhs) { lhs.x++; return lhs.x || rhs.x; } +struct MyStruct1 { + bool x; + MyStruct1(bool x) : x(x) {}; + operator bool() { return x; } +}; + +MyStruct1 operator&&(const MyStruct1& lhs, const MyStruct1& rhs) { return lhs.x && rhs.x; } +MyStruct1 operator||(MyStruct1& lhs, MyStruct1& rhs) { return lhs.x && rhs.x; } + bool TestOverloadedOperator(MyStruct& S) { if (S == Q) return false; @@ -180,6 +197,15 @@ bool TestOverloadedOperator(MyStruct& S) { if (S >= S) return true; // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of overloaded operator are equivalent + MyStruct1 U(false); + MyStruct1 V(true); + + // valid because the operator is not const + if ((U || V) || U) return true; + + if (U && V && U && V) return true; + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: overloaded operator has equivalent nested operands + return true; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp index a0a37c0ff1c7a..4f0713a01f6f4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp @@ -109,3 +109,21 @@ struct Template { Template TemplateInt; } + +struct AssignmentCallAtReturn { + AssignmentCallAtReturn &returnThis() { + return *this; + } + AssignmentCallAtReturn &operator=(int rhs) { + return *this; + } + AssignmentCallAtReturn &operator=(char rhs) { + // Allow call to assignment from other type. + return (*this = static_cast(rhs)); + } + AssignmentCallAtReturn &operator=(float rhs) { + // Do not allow calls to other functions. + return returnThis(); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this' + } +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp index 196eec91b8e8a..3570fcff4a5cc 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s modernize-use-default-member-init %t +// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s modernize-use-default-member-init %t -- -- -fexceptions // FIXME: Fix the checker to work in C++2a mode. struct S { @@ -418,3 +418,17 @@ NegativeTemplateExisting nted(0); }; MACRO(); + + +class FunctionTryBlock { +public: + FunctionTryBlock() try : i(5), k(8) {} + // CHECK-FIXES: FunctionTryBlock() try {} + catch (...) {} + +private: + int i, k; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' [modernize-use-default-member-init] + // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: use default member initializer for 'k' [modernize-use-default-member-init] + // CHECK-FIXES: int i{5}, k{8}; +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-cstr.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-cstr.cpp index d8434d3ca7c5a..1773dc57a8d88 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-cstr.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-cstr.cpp @@ -205,3 +205,18 @@ void dummy(const char*) {} void invalid(const NotAString &s) { dummy(s.c_str()); } + +// Test for rvalue std::string. +void m1(std::string&&) { + std::string s; + + m1(s.c_str()); + + void (*m1p1)(std::string&&); + m1p1 = m1; + m1p1(s.c_str()); + + using m1tp = void (*)(std::string &&); + m1tp m1p2 = m1; + m1p2(s.c_str()); +} diff --git a/clang/.arcconfig b/clang/.arcconfig deleted file mode 100644 index b258e7a34c4d6..0000000000000 --- a/clang/.arcconfig +++ /dev/null @@ -1,4 +0,0 @@ -{ - "repository.callsign" : "C", - "conduit_uri" : "https://reviews.llvm.org/" -} diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 0bd3faef5c24c..6d8f23c0d3f9f 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -874,7 +874,7 @@ add_subdirectory(utils/hmaptool) if(CLANG_BUILT_STANDALONE) llvm_distribution_add_targets() - process_llvm_pass_plugins(NO_GEN) + process_llvm_pass_plugins() endif() configure_file( diff --git a/clang/bindings/python/tests/cindex/test_diagnostics.py b/clang/bindings/python/tests/cindex/test_diagnostics.py index 52928db730355..64d0ca2ef9bcd 100644 --- a/clang/bindings/python/tests/cindex/test_diagnostics.py +++ b/clang/bindings/python/tests/cindex/test_diagnostics.py @@ -100,7 +100,7 @@ def test_diagnostic_children(self): self.assertRegexpMatches(children[0].spelling, '.*declared here') self.assertEqual(children[0].location.line, 1) - self.assertEqual(children[0].location.column, 1) + self.assertEqual(children[0].location.column, 6) def test_diagnostic_string_repr(self): tu = get_tu('struct MissingSemicolon{}') diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 4489dd4864f45..ff553deca82f9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -122,7 +122,7 @@ of ``cxx_rvalue_references``. ``__has_cpp_attribute`` ----------------------- -This function-like macro is available in C++2a by default, and is provided as an +This function-like macro is available in C++20 by default, and is provided as an extension in earlier language standards. It takes a single argument that is the name of a double-square-bracket-style attribute. The argument can either be a single identifier or a scoped identifier. If the attribute is supported, a @@ -1255,6 +1255,34 @@ the clang implementation are in :doc:`Block-ABI-Apple`. Query for this feature with ``__has_extension(blocks)``. +ASM Goto with Output Constraints +================================ + +In addition to the functionality provided by `GCC's extended +assembly``_, clang +supports output constraints with the `goto` form. + +The goto form of GCC's extended assembly allows the programmer to branch to a C +label from within an inline assembly block. Clang extends this behavior by +allowing the programmer to use output constraints: + +.. code-block:: c++ + + int foo(int x) { + int y; + asm goto("# %0 %1 %l2" : "=r"(y) : "r"(x) : : err); + return y; + err: + return -1; + } + +It's important to note that outputs are valid only on the "fallthrough" branch. +Using outputs on an indirect branch may result in undefined behavior. For +example, in the function above, use of the value assigned to `y` in the `err` +block is undefined behavior. + +Query for this feature with ``__has_extension(gnu_asm_goto_with_outputs)``. + Objective-C Features ==================== diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 05272a55ff017..d6f6b9132bcdd 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2128,6 +2128,16 @@

Narrowing Matchers

+Matcher<BinaryOperator>hasAnyOperatorNameStringRef, ..., StringRef +
Matches operator expressions (binary or unary) that have any of the
+specified names.
+
+   hasAnyOperatorName("+", "-")
+ Is equivalent to
+   anyOf(hasOperatorName("+"), hasOperatorName("-"))
+
+ + Matcher<BinaryOperator>hasOperatorNamestd::string Name
Matches the operator Name of operator expressions (binary or
 unary).
@@ -2948,6 +2958,19 @@ 

Narrowing Matchers

+Matcher<Decl>isInstantiated +
Matches declarations that are template instantiations or are inside
+template instantiations.
+
+Given
+  template<typename T> void A(T t) { T i; }
+  A(0);
+  A(0U);
+functionDecl(isInstantiated())
+  matches 'A(int) {...};' and 'A(unsigned) {...}'.
+
+ + Matcher<Decl>isPrivate
Matches private C++ declarations.
 
@@ -3516,6 +3539,16 @@ 

Narrowing Matchers

+Matcher<NamedDecl>hasAnyNameStringRef, ..., StringRef +
Matches NamedDecl nodes that have any of the specified names.
+
+This matcher is only provided as a performance optimization of hasName.
+    hasAnyName(a, b, c)
+ is equivalent to, but faster than
+    anyOf(hasName(a), hasName(b), hasName(c))
+
+ + Matcher<NamedDecl>hasExternalFormalLinkage
Matches a declaration that has external formal linkage.
 
@@ -3679,6 +3712,17 @@ 

Narrowing Matchers

+Matcher<ObjCMessageExpr>hasAnySelectorStringRef, ..., StringRef +
Matches when at least one of the supplied string equals to the
+Selector.getAsString()
+
+ matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+ matches both of the expressions below:
+    [myObj methodA:argA];
+    [myObj methodB:argB];
+
+ + Matcher<ObjCMessageExpr>hasKeywordSelector
Matches when the selector is a keyword selector
 
@@ -4015,6 +4059,17 @@ 

Narrowing Matchers

+Matcher<Stmt>isExpandedFromMacrollvm::StringRef MacroName +
Matches statements that are (transitively) expanded from the named macro.
+Does not match if only part of the statement is expanded from that macro or
+if different parts of the the statement are expanded from different
+appearances of the macro.
+
+FIXME: Change to be a polymorphic matcher that works on any syntactic
+node. There's nothing `Stmt`-specific about it.
+
+ + Matcher<Stmt>isExpansionInFileMatchingstd::string RegExp
Matches AST nodes that were expanded within files whose name is
 partially matching a given regex.
@@ -4058,6 +4113,22 @@ 

Narrowing Matchers

+Matcher<Stmt>isInTemplateInstantiation +
Matches statements inside of a template instantiation.
+
+Given
+  int j;
+  template<typename T> void A(T t) { T i; j += 42;}
+  A(0);
+  A(0U);
+declStmt(isInTemplateInstantiation())
+  matches 'int i;' and 'unsigned i'.
+unless(stmt(isInTemplateInstantiation()))
+  will NOT match j += 42; as it's shared between the template definition and
+  instantiation.
+
+ + Matcher<Stmt>isOMPStructuredBlock
Matches the Stmt AST node that is marked as being the structured-block
 of an OpenMP executable directive.
@@ -4312,6 +4383,16 @@ 

Narrowing Matchers

+Matcher<UnaryOperator>hasAnyOperatorNameStringRef, ..., StringRef +
Matches operator expressions (binary or unary) that have any of the
+specified names.
+
+   hasAnyOperatorName("+", "-")
+ Is equivalent to
+   anyOf(hasOperatorName("+"), hasOperatorName("-"))
+
+ + Matcher<UnaryOperator>hasOperatorNamestd::string Name
Matches the operator Name of operator expressions (binary or
 unary).
@@ -4551,56 +4632,6 @@ 

Narrowing Matchers

Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
- -Matcher<internal::Matcher<Decl>>isInstantiated -
Matches declarations that are template instantiations or are inside
-template instantiations.
-
-Given
-  template<typename T> void A(T t) { T i; }
-  A(0);
-  A(0U);
-functionDecl(isInstantiated())
-  matches 'A(int) {...};' and 'A(unsigned) {...}'.
-
- - -Matcher<internal::Matcher<NamedDecl>>hasAnyNameStringRef, ..., StringRef -
Matches NamedDecl nodes that have any of the specified names.
-
-This matcher is only provided as a performance optimization of hasName.
-    hasAnyName(a, b, c)
- is equivalent to, but faster than
-    anyOf(hasName(a), hasName(b), hasName(c))
-
- - -Matcher<internal::Matcher<ObjCMessageExpr>>hasAnySelectorStringRef, ..., StringRef -
Matches when at least one of the supplied string equals to the
-Selector.getAsString()
-
- matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
- matches both of the expressions below:
-    [myObj methodA:argA];
-    [myObj methodB:argB];
-
- - -Matcher<internal::Matcher<Stmt>>isInTemplateInstantiation -
Matches statements inside of a template instantiation.
-
-Given
-  int j;
-  template<typename T> void A(T t) { T i; j += 42;}
-  A(0);
-  A(0U);
-declStmt(isInTemplateInstantiation())
-  matches 'int i;' and 'unsigned i'.
-unless(stmt(isInTemplateInstantiation()))
-  will NOT match j += 42; as it's shared between the template definition and
-  instantiation.
-
- @@ -6600,6 +6631,12 @@

AST Traversal Matchers

+Matcher<NestedNameSpecifierLoc>locMatcher<NestedNameSpecifier> InnerMatcher +
Matches NestedNameSpecifierLocs for which the given inner
+NestedNameSpecifier-matcher matches.
+
+ + Matcher<NestedNameSpecifierLoc>specifiesTypeLocMatcher<TypeLoc> InnerMatcher
Matches nested name specifier locs that specify a type matching the
 given TypeLoc.
@@ -7401,6 +7438,12 @@ 

AST Traversal Matchers

+Matcher<TypeLoc>locMatcher<QualType> InnerMatcher +
Matches TypeLocs for which the given inner
+QualType-matcher matches.
+
+ + Matcher<TypedefNameDecl>hasTypeMatcher<QualType> InnerMatcher
Matches if the expression's or declaration's type matches a type
 matcher.
@@ -7636,18 +7679,6 @@ 

AST Traversal Matchers

if (true) {}
- -Matcher<internal::BindableMatcher<NestedNameSpecifierLoc>>locMatcher<NestedNameSpecifier> InnerMatcher -
Matches NestedNameSpecifierLocs for which the given inner
-NestedNameSpecifier-matcher matches.
-
- - -Matcher<internal::BindableMatcher<TypeLoc>>locMatcher<QualType> InnerMatcher -
Matches TypeLocs for which the given inner
-QualType-matcher matches.
-
- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ba3937dd83edc..831ef32c6b8a4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -66,6 +66,13 @@ New Compiler Flags attack for x86 architecture through automatic probing of each page of allocated stack. +- -ffp-exception-behavior={ignore,maytrap,strict} allows the user to specify + the floating-point exception behavior. The default setting is ``ignore``. + +- -ffp-model={precise,strict,fast} provides the user an umbrella option to + simplify access to the many single purpose floating point options. The default + setting is ``precise``. + Deprecated Compiler Flags ------------------------- diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index f39bf1f7b2b8d..b130cc34f6851 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -1929,6 +1929,38 @@ Warns against using one vs. many plural pattern in code when generating localize alpha.security ^^^^^^^^^^^^^^ + + +alpha.security.cert +^^^^^^^^^^^^^^^^^^^ + +SEI CERT checkers which tries to find errors based on their `C coding rules`_. + +.. _alpha-security-cert-pos-checkers: + +alpha.security.cert.pos +^^^^^^^^^^^^^^^^^^^^^^^ + +SEI CERT checkers of POSIX `C coding rules`_. + +.. _alpha-security-cert-pos-34c: + +alpha.security.cert.pos.34c +""""""""""""""""""""""""""" +Finds calls to the ``putenv`` function which pass a pointer to an automatic variable as the argument. + +.. code-block:: c + + int func(const char *var) { + char env[1024]; + int retval = snprintf(env, sizeof(env),"TEST=%s", var); + if (retval < 0 || (size_t)retval >= sizeof(env)) { + /* Handle error */ + } + + return putenv(env); // putenv function should not be called with auto variables + } + .. _alpha-security-ArrayBound: alpha.security.ArrayBound (C) diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py index c96c1ca27acb6..a8f284d55b649 100755 --- a/clang/docs/tools/dump_ast_matchers.py +++ b/clang/docs/tools/dump_ast_matchers.py @@ -103,6 +103,11 @@ def unify_arguments(args): args = re.sub(r'(^|\s)M\d?(\s)', r'\1Matcher<*>\2', args) return args +def unify_type(result_type): + """Gets rid of anything the user doesn't care about in the type name.""" + result_type = re.sub(r'^internal::(Bindable)?Matcher<([a-zA-Z_][a-zA-Z0-9_]*)>$', r'\2', result_type) + return result_type + def add_matcher(result_type, name, args, comment, is_dyncast=False): """Adds a matcher to one of our categories.""" if name == 'id': @@ -111,6 +116,7 @@ def add_matcher(result_type, name, args, comment, is_dyncast=False): matcher_id = '%s%d' % (name, ids[name]) ids[name] += 1 args = unify_arguments(args) + result_type = unify_type(result_type) matcher_html = TD_TEMPLATE % { 'result': esc('Matcher<%s>' % result_type), 'name': name, @@ -278,6 +284,22 @@ def act_on_decl(declaration, comment, allowed_types): add_matcher(result, name, '%s, ..., %s' % (arg, arg), comment) return + m = re.match( + r"""^.*internal::VariadicFunction\s*<\s* + internal::PolymorphicMatcherWithParam1<[\S\s]+ + AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)>,\s*([^,]+), + \s*[^>]+>\s*([a-zA-Z]*);$""", + declaration, flags=re.X) + + if m: + results, arg, name = m.groups()[:3] + + result_types = [r.strip() for r in results.split(',')] + for result_type in result_types: + add_matcher(result_type, name, '%s, ..., %s' % (arg, arg), comment) + return + + # Parse Variadic operator matchers. m = re.match( r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s]+)\s*>\s* diff --git a/clang/examples/clang-interpreter/main.cpp b/clang/examples/clang-interpreter/main.cpp index c0aae47223068..6b4cdca15fb09 100644 --- a/clang/examples/clang-interpreter/main.cpp +++ b/clang/examples/clang-interpreter/main.cpp @@ -54,7 +54,7 @@ class SimpleJIT { std::unique_ptr TM; const DataLayout DL; MangleAndInterner Mangle{ES, DL}; - JITDylib &MainJD{ES.createJITDylib("
")}; + JITDylib &MainJD{ES.createBareJITDylib("
")}; RTDyldObjectLinkingLayer ObjectLayer{ES, createMemMgr}; IRCompileLayer CompileLayer{ES, ObjectLayer, std::make_unique(*TM)}; diff --git a/clang/include/clang/AST/CommentSema.h b/clang/include/clang/AST/CommentSema.h index 307618fa5363c..6dfe0f4920d06 100644 --- a/clang/include/clang/AST/CommentSema.h +++ b/clang/include/clang/AST/CommentSema.h @@ -217,6 +217,9 @@ class Sema { bool isTemplateOrSpecialization(); bool isRecordLikeDecl(); bool isClassOrStructDecl(); + /// \return \c true if the declaration that this comment is attached to + /// declares either struct, class or tag typedef. + bool isClassOrStructOrTagTypedefDecl(); bool isUnionDecl(); bool isObjCInterfaceDecl(); bool isObjCProtocolDecl(); diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 24c1abb2be549..5cc4eb8a46dfc 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -3032,7 +3032,7 @@ class GCCAsmStmt : public AsmStmt { } IdentifierInfo *getLabelIdentifier(unsigned i) const { - return Names[i + NumInputs]; + return Names[i + NumOutputs + NumInputs]; } AddrLabelExpr *getLabelExpr(unsigned i) const; @@ -3043,11 +3043,11 @@ class GCCAsmStmt : public AsmStmt { using labels_const_range = llvm::iterator_range; labels_iterator begin_labels() { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } labels_iterator end_labels() { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_range labels() { @@ -3055,11 +3055,11 @@ class GCCAsmStmt : public AsmStmt { } const_labels_iterator begin_labels() const { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } const_labels_iterator end_labels() const { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_const_range labels() const { diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 5565417c7c1f9..d45825de67db2 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -307,7 +307,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, /// /// FIXME: Change to be a polymorphic matcher that works on any syntactic /// node. There's nothing `Stmt`-specific about it. -AST_MATCHER_P(clang::Stmt, isExpandedFromMacro, llvm::StringRef, MacroName) { +AST_MATCHER_P(Stmt, isExpandedFromMacro, llvm::StringRef, MacroName) { // Verifies that the statement' beginning and ending are both expanded from // the same instance of the given macro. auto& Context = Finder->getASTContext(); @@ -4762,6 +4762,19 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, return Name == Node.getOpcodeStr(Node.getOpcode()); } +/// Matches operator expressions (binary or unary) that have any of the +/// specified names. +/// +/// hasAnyOperatorName("+", "-") +/// Is equivalent to +/// anyOf(hasOperatorName("+"), hasOperatorName("-")) +extern const internal::VariadicFunction< + internal::PolymorphicMatcherWithParam1< + internal::HasAnyOperatorNameMatcher, std::vector, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, UnaryOperator)>, + StringRef, internal::hasAnyOperatorNameFunc> + hasAnyOperatorName; + /// Matches all kinds of assignment operators. /// /// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator())) diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 03eb1f79eea0f..6e4310fa0ee84 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1858,6 +1858,47 @@ CompoundStmtMatcher::get(const StmtExpr &Node) { llvm::Optional getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc, const ASTContext &Context); + +/// Matches overloaded operators with a specific name. +/// +/// The type argument ArgT is not used by this matcher but is used by +/// PolymorphicMatcherWithParam1 and should be std::vector>. +template > +class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface { + static_assert(std::is_same::value || + std::is_same::value, + "Matcher only supports `BinaryOperator` and `UnaryOperator`"); + static_assert(std::is_same>::value, + "Matcher ArgT must be std::vector"); + +public: + explicit HasAnyOperatorNameMatcher(std::vector Names) + : SingleNodeMatcherInterface(), Names(std::move(Names)) {} + + bool matchesNode(const T &Node) const override { + StringRef OpName = getOpName(Node); + return llvm::any_of( + Names, [&](const std::string &Name) { return Name == OpName; }); + } + +private: + static StringRef getOpName(const UnaryOperator &Node) { + return Node.getOpcodeStr(Node.getOpcode()); + } + static StringRef getOpName(const BinaryOperator &Node) { + return Node.getOpcodeStr(); + } + + const std::vector Names; +}; + +using HasOpNameMatcher = + PolymorphicMatcherWithParam1, + void(TypeList)>; + +HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef NameRefs); + } // namespace internal } // namespace ast_matchers diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index 1d96ba6231cf0..4977bf32e9f6e 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -134,9 +134,8 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public ::clang::ast_matchers::internal::MatcherInterface { \ public: \ - explicit matcher_##DefineMatcher##OverloadId##Matcher( \ - ParamType const &A##Param) \ - : Param(A##Param) {} \ + explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \ + : Param(std::move(A##Param)) {} \ bool matches(const Type &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ @@ -147,12 +146,13 @@ }; \ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ - ParamType const &Param) { \ + ParamType Param) { \ return ::clang::ast_matchers::internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher( \ + std::move(Param))); \ } \ - typedef ::clang::ast_matchers::internal::Matcher( \ - &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \ + typedef ::clang::ast_matchers::internal::Matcher ( \ + &DefineMatcher##_Type##OverloadId)(ParamType Param); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ @@ -183,9 +183,9 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public ::clang::ast_matchers::internal::MatcherInterface { \ public: \ - matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ - ParamType2 const &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ + matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \ + ParamType2 A##Param2) \ + : Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \ bool matches(const Type &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ @@ -197,14 +197,14 @@ }; \ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ - ParamType1 const &Param1, ParamType2 const &Param2) { \ + ParamType1 Param1, ParamType2 Param2) { \ return ::clang::ast_matchers::internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ - Param2)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher( \ + std::move(Param1), std::move(Param2))); \ } \ - typedef ::clang::ast_matchers::internal::Matcher( \ - &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \ - ParamType2 const &Param2); \ + typedef ::clang::ast_matchers::internal::Matcher ( \ + &DefineMatcher##_Type##OverloadId)(ParamType1 Param1, \ + ParamType2 Param2); \ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ @@ -272,9 +272,8 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public ::clang::ast_matchers::internal::MatcherInterface { \ public: \ - explicit matcher_##DefineMatcher##OverloadId##Matcher( \ - ParamType const &A##Param) \ - : Param(A##Param) {} \ + explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \ + : Param(std::move(A##Param)) {} \ bool matches(const NodeType &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ @@ -287,15 +286,14 @@ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ ReturnTypesF> \ - DefineMatcher(ParamType const &Param) { \ + DefineMatcher(ParamType Param) { \ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF>(Param); \ + ReturnTypesF>(std::move(Param)); \ } \ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ - ParamType const &Param); \ + ReturnTypesF> (&DefineMatcher##_Type##OverloadId)(ParamType Param); \ template \ bool internal:: \ matcher_##DefineMatcher##OverloadId##Matcher::matches( \ @@ -325,9 +323,9 @@ class matcher_##DefineMatcher##OverloadId##Matcher \ : public ::clang::ast_matchers::internal::MatcherInterface { \ public: \ - matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \ - ParamType2 const &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ + matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \ + ParamType2 A##Param2) \ + : Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \ bool matches(const NodeType &Node, \ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ @@ -341,15 +339,15 @@ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2, ReturnTypesF> \ - DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \ + DefineMatcher(ParamType1 Param1, ParamType2 Param2) { \ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF>(Param1, Param2); \ + ParamType2, ReturnTypesF>(std::move(Param1), std::move(Param2)); \ } \ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ - ParamType1 const &Param1, ParamType2 const &Param2); \ + ParamType2, ReturnTypesF> (&DefineMatcher##_Type##OverloadId)( \ + ParamType1 Param1, ParamType2 Param2); \ template \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT1, ParamT2>:: \ diff --git a/clang/include/clang/ASTMatchers/GtestMatchers.h b/clang/include/clang/ASTMatchers/GtestMatchers.h new file mode 100644 index 0000000000000..4f8addcf744ae --- /dev/null +++ b/clang/include/clang/ASTMatchers/GtestMatchers.h @@ -0,0 +1,45 @@ +//===- GtestMatchers.h - AST Matchers for GTest -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements matchers specific to structures in the Googletest +// (gtest) framework. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H +#define LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H + +#include "clang/AST/Stmt.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang { +namespace ast_matchers { + +/// Gtest's comparison operations. +enum class GtestCmp { + Eq, + Ne, + Ge, + Gt, + Le, + Lt, +}; + +/// Matcher for gtest's ASSERT_... macros. +internal::BindableMatcher gtestAssert(GtestCmp Cmp, StatementMatcher Left, + StatementMatcher Right); + +/// Matcher for gtest's EXPECT_... macros. +internal::BindableMatcher gtestExpect(GtestCmp Cmp, StatementMatcher Left, + StatementMatcher Right); + +} // namespace ast_matchers +} // namespace clang + +#endif // LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H + diff --git a/clang/include/clang/Analysis/AnyCall.h b/clang/include/clang/Analysis/AnyCall.h index 97a94d299e64c..16371eb1da183 100644 --- a/clang/include/clang/Analysis/AnyCall.h +++ b/clang/include/clang/Analysis/AnyCall.h @@ -41,6 +41,9 @@ class AnyCall { /// An implicit or explicit C++ constructor call Constructor, + /// A C++ inherited constructor produced by a "using T::T" directive + InheritedConstructor, + /// A C++ allocation function call (operator `new`), via C++ new-expression Allocator, @@ -84,6 +87,9 @@ class AnyCall { AnyCall(const CXXConstructExpr *NE) : E(NE), D(NE->getConstructor()), K(Constructor) {} + AnyCall(const CXXInheritedCtorInitExpr *CIE) + : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {} + AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {} AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {} @@ -114,6 +120,8 @@ class AnyCall { return AnyCall(CXDE); } else if (const auto *CXCE = dyn_cast(E)) { return AnyCall(CXCE); + } else if (const auto *CXCIE = dyn_cast(E)) { + return AnyCall(CXCIE); } else { return None; } @@ -169,6 +177,7 @@ class AnyCall { return cast(E)->getCallReturnType(Ctx); case Destructor: case Constructor: + case InheritedConstructor: case Allocator: case Deallocator: return cast(D)->getReturnType(); diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h index 0e56d1c006232..0410503192392 100644 --- a/clang/include/clang/Analysis/CallGraph.h +++ b/clang/include/clang/Analysis/CallGraph.h @@ -189,6 +189,10 @@ class CallGraphNode { Decl *getDecl() const { return FD; } + FunctionDecl *getDefinition() const { + return getDecl()->getAsFunction()->getDefinition(); + } + void print(raw_ostream &os) const; void dump() const; }; diff --git a/clang/include/clang/Analysis/ConstructionContext.h b/clang/include/clang/Analysis/ConstructionContext.h index f1564f9fe740e..4fa5c8b454a03 100644 --- a/clang/include/clang/Analysis/ConstructionContext.h +++ b/clang/include/clang/Analysis/ConstructionContext.h @@ -110,6 +110,9 @@ class ConstructionContextItem { ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index) : Data(CE), Kind(ArgumentKind), Index(Index) {} + ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index) + : Data(CE), Kind(ArgumentKind), Index(Index) {} + ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index) : Data(ME), Kind(ArgumentKind), Index(Index) {} @@ -117,7 +120,7 @@ class ConstructionContextItem { ConstructionContextItem(const Expr *E, unsigned Index) : Data(E), Kind(ArgumentKind), Index(Index) { assert(isa(E) || isa(E) || - isa(E)); + isa(E) || isa(E)); } ConstructionContextItem(const CXXCtorInitializer *Init) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1f05f632c3e9d..fc8d392e3937a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1823,6 +1823,15 @@ def SYCLFPGAPipe : TypeAttr { let Documentation = [SYCLFPGAPipeDocs]; } +def SYCLIntelPipeIO : Attr { + let Spellings = [GNU<"io_pipe_id">]; + let Args = [ExprArgument<"ID">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let Subjects = SubjectList<[Var]>; + let Documentation = [SYCLIntelPipeIOAttrDocs]; + let PragmaAttributeSupport = 0; +} + // Variadic integral arguments. def IntelFPGABankBits : Attr { let Spellings = [CXX11<"intelfpga", "bank_bits">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 54db7c2370e91..58af06c66bb84 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2033,6 +2033,20 @@ write only. Expected to be used only in SYCL headers. }]; } +def SYCLIntelPipeIOAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "IO pipe ID"; + let Content = [{ +Add I/O attribute to SYCL pipe declaration to declare a special I/O pipe to +interface with input or output features of an FPGA. These features might include +network interfaces, PCIe, cameras, or other data capture or processing devices +or protocols. + +The io_pipe_id(id) attribute specifies the I/O feature of an accelerator board +with which a pipe interfaces. The id argument is the name of the I/O interface. + }]; +} + def SYCLIntelFPGAIVDepAttrDocs : Documentation { let Category = DocCatVariable; let Heading = "ivdep"; diff --git a/clang/include/clang/Basic/BuiltinsHexagon.def b/clang/include/clang/Basic/BuiltinsHexagon.def index 40fdbeffdf513..28aa222166f53 100644 --- a/clang/include/clang/Basic/BuiltinsHexagon.def +++ b/clang/include/clang/Basic/BuiltinsHexagon.def @@ -96,14 +96,14 @@ TARGET_BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "", V5) TARGET_BUILTIN(__builtin_HEXAGON_prefetch,"vv*","", V5) TARGET_BUILTIN(__builtin_HEXAGON_A6_vminub_RdP,"LLiLLiLLi","", V62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV16iv*V16i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV16iv*V16i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV16iv*V16i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV16iv*V16i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV32iv*V32i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV32iv*V32i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV32iv*V32i","", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV32iv*V32i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV64bv*V16i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV64bv*V16i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV64bv*V16i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV64bv*V16i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV128bv*V32i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV128bv*V32i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV128bv*V32i","", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV128bv*V32i","", HVXV60) // These are only valid on v65 diff --git a/clang/include/clang/Basic/BuiltinsHexagonDep.def b/clang/include/clang/Basic/BuiltinsHexagonDep.def index 93fa373244d75..b694e4c35d3bd 100644 --- a/clang/include/clang/Basic/BuiltinsHexagonDep.def +++ b/clang/include/clang/Basic/BuiltinsHexagonDep.def @@ -924,14 +924,14 @@ TARGET_BUILTIN(__builtin_HEXAGON_F2_dfmpyhh, "dddd", "", V67) // V60 HVX Instructions. -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai, "vV16iv*V16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B, "vV32iv*V32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai, "vV16iv*V16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B, "vV32iv*V32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai, "vV16iv*V16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B, "vV32iv*V32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai, "vV16iv*V16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B, "vV32iv*V32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai, "vV64bv*V16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B, "vV128bv*V32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai, "vV64bv*V16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B, "vV128bv*V32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai, "vV64bv*V16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B, "vV128bv*V32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai, "vV64bv*V16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B, "vV128bv*V32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_valignb, "V16iV16iV16ii", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_valignb_128B, "V32iV32iV32ii", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vlalignb, "V16iV16iV16ii", "", HVXV60) @@ -1212,30 +1212,30 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubuhw, "V32iV16iV16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubuhw_128B, "V64iV32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vd0, "V16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vd0_128B, "V32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbnq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbnq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhnq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhnq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwnq_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwnq, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwnq_128B, "V32iV32iV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddbnq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubbnq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddhnq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubhnq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddwnq_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwnq, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vsubwnq_128B, "V32iV128bV32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vabsh, "V16iV16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vabsh_128B, "V32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vabsh_sat, "V16iV16i", "", HVXV60) @@ -1346,104 +1346,104 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vxor, "V16iV16iV16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vxor_128B, "V32iV32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vnot, "V16iV16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vnot_128B, "V32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt, "V16iV16ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_128B, "V32iV32ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc, "V16iV16iV16ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc_128B, "V32iV32iV32ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt, "V16iV16ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_128B, "V32iV32ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc, "V16iV16iV16ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc_128B, "V32iV32iV32ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_and, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_and_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_or, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_or_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_xor, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_xor_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_not, "V16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_not_128B, "V32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_xor, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_xor_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_n, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_n_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_n, "V16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_n_128B, "V32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2, "V16ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2_128B, "V32ii", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmux, "V16iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vmux_128B, "V32iV32iV32iV32i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vswap, "V32iV16iV16iV16i", "", HVXV60) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vswap_128B, "V64iV32iV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt, "V16iV64bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_128B, "V32iV128bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc, "V16iV16iV64bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc_128B, "V32iV32iV128bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt, "V64bV16ii", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_128B, "V128bV32ii", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc, "V64bV64bV16ii", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc_128B, "V128bV128bV32ii", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtw_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqw_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgth_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqh_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtb_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_veqb_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub, "V64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_128B, "V128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_and, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_and_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_or, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_or_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_xor, "V64bV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgtub_xor_128B, "V128bV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or, "V64bV64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_128B, "V128bV128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and, "V64bV64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_128B, "V128bV128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_not, "V64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_not_128B, "V128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_xor, "V64bV64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_xor_128B, "V128bV128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_n, "V64bV64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_and_n_128B, "V128bV128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_n, "V64bV64bV64b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_or_n_128B, "V128bV128bV128b", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2, "V64bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2_128B, "V128bi", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmux, "V16iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vmux_128B, "V32iV128bV32iV32i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vswap, "V32iV64bV16iV16i", "", HVXV60) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vswap_128B, "V64iV128bV32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaxub, "V16iV16iV16i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaxub_128B, "V32iV32iV32i", "", HVXV60) TARGET_BUILTIN(__builtin_HEXAGON_V6_vminub, "V16iV16iV16i", "", HVXV60) @@ -1585,20 +1585,20 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vmpyiwub, "V16iV16ii", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_128B, "V32iV32ii", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc, "V16iV16iV16ii", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc_128B, "V32iV32iV32ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt, "V16iV16ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B, "V32iV32ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc, "V16iV16iV16ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B, "V32iV32iV32ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvqv, "V16iV16iV16i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B, "V32iV32iV32i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvnqv, "V16iV16iV16i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B, "V32iV32iV32i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2, "V16ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B, "V32ii", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqw, "V16iV16iV16i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B, "V32iV32iV32i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqh, "V16iV16iV16i", "", HVXV62) -TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B, "V32iV32iV32i", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt, "V16iV64bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B, "V32iV128bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc, "V16iV16iV64bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B, "V32iV32iV128bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvqv, "V16iV64bV16i", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B, "V32iV128bV32i", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvnqv, "V16iV64bV16i", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B, "V32iV128bV32i", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2, "V64bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B, "V128bi", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqw, "V64bV64bV64b", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B, "V128bV128bV128b", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqh, "V64bV64bV64b", "", HVXV62) +TARGET_BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B, "V128bV128bV128b", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaxb, "V16iV16iV16i", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vmaxb_128B, "V32iV32iV32i", "", HVXV62) TARGET_BUILTIN(__builtin_HEXAGON_V6_vminb, "V16iV16iV16i", "", HVXV62) @@ -1678,12 +1678,12 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermh, "vv*iiV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermh_128B, "vv*iiV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhw, "vv*iiV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhw_128B, "vv*iiV64i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermwq, "vv*V16iiiV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B, "vv*V32iiiV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhq, "vv*V16iiiV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B, "vv*V32iiiV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhwq, "vv*V16iiiV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B, "vv*V32iiiV64i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermwq, "vv*V64biiV16i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B, "vv*V128biiV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhq, "vv*V64biiV16i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B, "vv*V128biiV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhwq, "vv*V64biiV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B, "vv*V128biiV64i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermw, "viiV16iV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermw_128B, "viiV32iV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermh, "viiV16iV16i", "", HVXV65) @@ -1692,22 +1692,22 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermw_add, "viiV16iV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermw_add_128B, "viiV32iV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermh_add, "viiV16iV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermh_add_128B, "viiV32iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermwq, "vV16iiiV16iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B, "vV32iiiV32iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhq, "vV16iiiV16iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B, "vV32iiiV32iV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermwq, "vV64biiV16iV16i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B, "vV128biiV32iV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhq, "vV64biiV16iV16i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B, "vV128biiV32iV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhw, "viiV32iV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhw_128B, "viiV64iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhwq, "vV16iiiV32iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B, "vV32iiiV64iV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhwq, "vV64biiV32iV16i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B, "vV128biiV64iV32i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add, "viiV32iV16i", "", HVXV65) TARGET_BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add_128B, "viiV64iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqb, "V16iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B, "V32iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqh, "V16iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B, "V32iV32i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqw, "V16iV16i", "", HVXV65) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B, "V32iV32i", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqb, "V16iV64b", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B, "V32iV128b", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqh, "V16iV64b", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B, "V32iV128b", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqw, "V16iV64b", "", HVXV65) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B, "V32iV128b", "", HVXV65) // V66 HVX Instructions. @@ -1715,7 +1715,7 @@ TARGET_BUILTIN(__builtin_HEXAGON_V6_vrotr, "V16iV16iV16i", "", HVXV66) TARGET_BUILTIN(__builtin_HEXAGON_V6_vrotr_128B, "V32iV32iV32i", "", HVXV66) TARGET_BUILTIN(__builtin_HEXAGON_V6_vasr_into, "V32iV32iV16iV16i", "", HVXV66) TARGET_BUILTIN(__builtin_HEXAGON_V6_vasr_into_128B, "V64iV64iV32iV32i", "", HVXV66) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat, "V16iV16iV16iV16i", "", HVXV66) -TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat_128B, "V32iV32iV32iV32i", "", HVXV66) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat, "V16iV16iV16iV64b", "", HVXV66) +TARGET_BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat_128B, "V32iV32iV32iV128b", "", HVXV66) TARGET_BUILTIN(__builtin_HEXAGON_V6_vsatdw, "V16iV16iV16i", "", HVXV66) TARGET_BUILTIN(__builtin_HEXAGON_V6_vsatdw_128B, "V32iV32iV32i", "", HVXV66) diff --git a/clang/include/clang/Basic/BuiltinsHexagonMapCustomDep.def b/clang/include/clang/Basic/BuiltinsHexagonMapCustomDep.def new file mode 100644 index 0000000000000..9478a1b3fd140 --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsHexagonMapCustomDep.def @@ -0,0 +1,206 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// Automatically generated file, do not edit! +//===----------------------------------------------------------------------===// + +CUSTOM_BUILTIN_MAPPING(M2_mpysmi, 0) +CUSTOM_BUILTIN_MAPPING(M2_dpmpyss_s0, 0) +CUSTOM_BUILTIN_MAPPING(M2_dpmpyuu_s0, 0) +CUSTOM_BUILTIN_MAPPING(M2_mpyi, 0) +CUSTOM_BUILTIN_MAPPING(M2_mpyui, 0) +CUSTOM_BUILTIN_MAPPING(A2_add, 0) +CUSTOM_BUILTIN_MAPPING(A2_sub, 0) +CUSTOM_BUILTIN_MAPPING(A2_addi, 0) +CUSTOM_BUILTIN_MAPPING(A2_addp, 0) +CUSTOM_BUILTIN_MAPPING(A2_subp, 0) +CUSTOM_BUILTIN_MAPPING(A2_neg, 0) +CUSTOM_BUILTIN_MAPPING(A2_zxtb, 0) +CUSTOM_BUILTIN_MAPPING(A2_sxtb, 0) +CUSTOM_BUILTIN_MAPPING(A2_zxth, 0) +CUSTOM_BUILTIN_MAPPING(A2_sxth, 0) +CUSTOM_BUILTIN_MAPPING(A2_and, 0) +CUSTOM_BUILTIN_MAPPING(A2_or, 0) +CUSTOM_BUILTIN_MAPPING(A2_xor, 0) +CUSTOM_BUILTIN_MAPPING(A2_not, 0) +CUSTOM_BUILTIN_MAPPING(A2_subri, 0) +CUSTOM_BUILTIN_MAPPING(A2_andir, 0) +CUSTOM_BUILTIN_MAPPING(A2_orir, 0) +CUSTOM_BUILTIN_MAPPING(S2_asr_i_r, 0) +CUSTOM_BUILTIN_MAPPING(S2_lsr_i_r, 0) +CUSTOM_BUILTIN_MAPPING(S2_asl_i_r, 0) +CUSTOM_BUILTIN_MAPPING(S2_asr_i_p, 0) +CUSTOM_BUILTIN_MAPPING(S2_lsr_i_p, 0) +CUSTOM_BUILTIN_MAPPING(S2_asl_i_p, 0) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_qpred_ai, 64) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_qpred_ai_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nqpred_ai, 64) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nqpred_ai_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_qpred_ai, 64) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_qpred_ai_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_nqpred_ai, 64) +CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_nqpred_ai_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddbq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddbq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubbq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubbq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddbnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddbnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubbnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubbnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddhq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddhq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubhq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubhq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddhnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddhnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubhnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubhnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddwnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddwnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubwnq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubwnq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandqrt, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandqrt_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandqrt_acc, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandqrt_acc_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandvrt, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandvrt_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandvrt_acc, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandvrt_acc_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtw, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtw_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqw, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqw_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqw_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqw_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqw_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqw_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqw_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqw_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgth, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgth_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgth_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgth_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgth_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgth_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgth_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgth_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqh, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqh_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqh_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqh_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqh_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqh_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqh_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqh_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtb, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtb_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqb, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqb_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqb_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqb_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqb_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqb_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_veqb_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_veqb_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuw_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtuh_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtub, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgtub_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_or, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_or_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_and, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_and_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_not, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_not_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_xor, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_xor_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_and_n, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_and_n_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_or_n, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_or_n_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vmux, 64) +CUSTOM_BUILTIN_MAPPING(V6_vmux_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vswap, 64) +CUSTOM_BUILTIN_MAPPING(V6_vswap_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddcarry, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddcarry_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vsubcarry, 64) +CUSTOM_BUILTIN_MAPPING(V6_vsubcarry_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandnqrt, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_acc, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_acc_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandvqv, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandvqv_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vandvnqv, 64) +CUSTOM_BUILTIN_MAPPING(V6_vandvnqv_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2v2, 64) +CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2v2_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_shuffeqw, 64) +CUSTOM_BUILTIN_MAPPING(V6_shuffeqw_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_shuffeqh, 64) +CUSTOM_BUILTIN_MAPPING(V6_shuffeqh_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgathermwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgathermwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgathermhq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgathermhq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vgathermhwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vgathermhwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vscattermwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vscattermwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vscattermhq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vscattermhq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vscattermhwq, 64) +CUSTOM_BUILTIN_MAPPING(V6_vscattermhwq_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqb, 64) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqb_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqh, 64) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqh_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqw, 64) +CUSTOM_BUILTIN_MAPPING(V6_vprefixqw_128B, 128) +CUSTOM_BUILTIN_MAPPING(V6_vaddcarrysat, 64) +CUSTOM_BUILTIN_MAPPING(V6_vaddcarrysat_128B, 128) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c0b737b08a72e..48bafeeff2085 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -13,7 +13,7 @@ def note_expr_divide_by_zero : Note<"division by zero">; def note_constexpr_invalid_cast : Note< "%select{reinterpret_cast|dynamic_cast|cast that performs the conversions of" " a reinterpret_cast|cast from %1}0 is not allowed in a constant expression" - "%select{| in C++ standards before C++2a||}0">; + "%select{| in C++ standards before C++20||}0">; def note_constexpr_invalid_downcast : Note< "cannot cast object of dynamic type %0 to type %1">; def note_constexpr_overflow : Note< @@ -33,7 +33,7 @@ def note_constexpr_no_return : Note< "control reached end of constexpr function">; def note_constexpr_virtual_call : Note< "cannot evaluate call to virtual function in a constant expression " - "in C++ standards before C++2a">; + "in C++ standards before C++20">; def note_constexpr_pure_virtual_call : Note< "pure virtual function %q0 called">; def note_constexpr_polymorphic_unknown_dynamic_type : Note< @@ -105,7 +105,7 @@ def note_constexpr_var_init_non_constant : Note< "initializer of %0 is not a constant expression">; def note_constexpr_typeid_polymorphic : Note< "typeid applied to expression of polymorphic type %0 is " - "not allowed in a constant expression in C++ standards before C++2a">; + "not allowed in a constant expression in C++ standards before C++20">; def note_constexpr_void_comparison : Note< "comparison between unequal pointers to void has unspecified result">; def note_constexpr_temporary_here : Note<"temporary created here">; diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 95cb81f09922a..5d8c939283b55 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -120,7 +120,7 @@ def err_enum_template : Error<"enumeration cannot be a template">; def warn_cxx20_compat_consteval : Warning< "'consteval' specifier is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; } diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index d7aceec8c3b10..47557f84f2d6b 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -287,6 +287,9 @@ def warn_drv_unsupported_debug_info_opt_for_target : Warning< InGroup; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; +def warn_ignoring_fdiscard_for_bitcode : Warning< + "ignoring -fdiscard-value-names for LLVM Bitcode">, + InGroup; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused%select{ when '%3' is present|}2">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index ed2092fb4c845..87fdfc89c634d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -106,7 +106,7 @@ def err_fe_invalid_wchar_type def err_fe_invalid_exception_model : Error<"invalid exception model '%0' for target '%1'">; def warn_fe_concepts_ts_flag : Warning< - "-fconcepts-ts is deprecated - use '-std=c++2a' for Concepts support">, + "-fconcepts-ts is deprecated - use '-std=c++20' for Concepts support">, InGroup; def warn_fe_serialized_diag_merge_failure : Warning< @@ -175,9 +175,9 @@ def note_incompatible_analyzer_plugin_api : Note< def err_module_build_requires_fmodules : Error< "module compilation requires '-fmodules'">; def err_module_interface_requires_cpp_modules : Error< - "module interface compilation requires '-std=c++2a' or '-fmodules-ts'">; + "module interface compilation requires '-std=c++20' or '-fmodules-ts'">; def err_header_module_requires_modules : Error< - "header module compilation requires '-fmodules', '-std=c++2a', or " + "header module compilation requires '-fmodules', '-std=c++20', or " "'-fmodules-ts'">; def warn_module_config_mismatch : Warning< "module file %0 cannot be loaded due to a configuration mismatch with the current " diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 633595d3f9999..4f74819911440 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -187,10 +187,10 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, DeprecatedWritableStr]>, DiagCategory<"Deprecations">; -def CXX2aDesignator : DiagGroup<"c++2a-designator">; +def CXX20Designator : DiagGroup<"c++20-designator">; // Allow -Wno-c99-designator to be used to turn off all warnings on valid C99 -// designators (including the warning controlled by -Wc++2a-designator). -def C99Designator : DiagGroup<"c99-designator", [CXX2aDesignator]>; +// designators (including the warning controlled by -Wc++20-designator). +def C99Designator : DiagGroup<"c99-designator", [CXX20Designator]>; def GNUDesignator : DiagGroup<"gnu-designator">; def DtorName : DiagGroup<"dtor-name">; @@ -247,9 +247,9 @@ def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", def CXXPre17Compat : DiagGroup<"c++98-c++11-c++14-compat">; def CXXPre17CompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", [CXXPre17Compat]>; -def CXXPre2aCompat : DiagGroup<"c++98-c++11-c++14-c++17-compat">; -def CXXPre2aCompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", - [CXXPre2aCompat]>; +def CXXPre20Compat : DiagGroup<"c++98-c++11-c++14-c++17-compat">; +def CXXPre20CompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", + [CXXPre20Compat]>; def CXX98CompatBindToTemporaryCopy : DiagGroup<"c++98-compat-bind-to-temporary-copy">; @@ -263,7 +263,7 @@ def CXX98Compat : DiagGroup<"c++98-compat", CXX98CompatUnnamedTypeTemplateArgs, CXXPre14Compat, CXXPre17Compat, - CXXPre2aCompat]>; + CXXPre20Compat]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, @@ -271,7 +271,7 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", CXX98CompatExtraSemi, CXXPre14CompatPedantic, CXXPre17CompatPedantic, - CXXPre2aCompatPedantic]>; + CXXPre20CompatPedantic]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; @@ -297,33 +297,35 @@ def CXX11Compat : DiagGroup<"c++11-compat", CXX11CompatDeprecatedWritableStr, CXXPre14Compat, CXXPre17Compat, - CXXPre2aCompat]>; + CXXPre20Compat]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", [CXX11Compat, CXXPre14CompatPedantic, CXXPre17CompatPedantic, - CXXPre2aCompatPedantic]>; + CXXPre20CompatPedantic]>; def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre17Compat, - CXXPre2aCompat]>; + CXXPre20Compat]>; def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic", [CXX14Compat, CXXPre17CompatPedantic, - CXXPre2aCompatPedantic]>; + CXXPre20CompatPedantic]>; def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister, DeprecatedIncrementBool, CXX17CompatMangling, - CXXPre2aCompat]>; + CXXPre20Compat]>; def CXX17CompatPedantic : DiagGroup<"c++17-compat-pedantic", [CXX17Compat, - CXXPre2aCompatPedantic]>; + CXXPre20CompatPedantic]>; def : DiagGroup<"c++1z-compat", [CXX17Compat]>; -def CXX2aCompat : DiagGroup<"c++2a-compat">; -def CXX2aCompatPedantic : DiagGroup<"c++2a-compat-pedantic", - [CXX2aCompat]>; +def CXX20Compat : DiagGroup<"c++20-compat">; +def CXX20CompatPedantic : DiagGroup<"c++20-compat-pedantic", + [CXX20Compat]>; +def : DiagGroup<"c++2a-compat", [CXX20Compat]>; +def : DiagGroup<"c++2a-compat-pedantic", [CXX20CompatPedantic]>; def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; @@ -961,13 +963,14 @@ def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>; // earlier C++ versions. def CXX17 : DiagGroup<"c++17-extensions">; -// A warning group for warnings about using C++2a features as extensions in +// A warning group for warnings about using C++20 features as extensions in // earlier C++ versions. -def CXX2a : DiagGroup<"c++2a-extensions", [CXX2aDesignator]>; +def CXX20 : DiagGroup<"c++20-extensions", [CXX20Designator]>; def : DiagGroup<"c++0x-extensions", [CXX11]>; def : DiagGroup<"c++1y-extensions", [CXX14]>; def : DiagGroup<"c++1z-extensions", [CXX17]>; +def : DiagGroup<"c++2a-extensions", [CXX20]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index b64cbc23f8100..9e0449d341047 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -31,12 +31,12 @@ def warn_cxx98_compat_less_colon_colon : Warning< InGroup, DefaultIgnore; def warn_cxx17_compat_spaceship : Warning< - "'<=>' operator is incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "'<=>' operator is incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def warn_cxx2a_compat_spaceship : Warning< - "'<=>' is a single token in C++2a; " + "'<=>' is a single token in C++20; " "add a space to avoid a change in behavior">, - InGroup; + InGroup; // Trigraphs. def trigraph_ignored : Warning<"trigraph ignored">, InGroup; @@ -78,8 +78,8 @@ def ext_token_used : Extension<"extension used">, def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">, InGroup, DefaultIgnore; -def warn_cxx2a_keyword : Warning<"'%0' is a keyword in C++2a">, - InGroup, DefaultIgnore; +def warn_cxx2a_keyword : Warning<"'%0' is a keyword in C++20">, + InGroup, DefaultIgnore; def ext_unterminated_char_or_string : ExtWarn< "missing terminating %select{'|'\"'}0 character">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 9410afb7aa027..4cc8608601dc5 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -241,10 +241,10 @@ def warn_cxx14_compat_nested_namespace_definition : Warning< "nested namespace definition is incompatible with C++ standards before C++17">, InGroup, DefaultIgnore; def ext_inline_nested_namespace_definition : ExtWarn< - "inline nested namespace definition is a C++2a extension">, InGroup; + "inline nested namespace definition is a C++20 extension">, InGroup; def warn_cxx17_compat_inline_nested_namespace_definition : Warning< "inline nested namespace definition is incompatible with C++ standards before" - " C++2a">, InGroup, DefaultIgnore; + " C++20">, InGroup, DefaultIgnore; def err_inline_nested_namespace_definition : Error< "nested namespace definition cannot be 'inline'">; def err_expected_semi_after_attribute_list : Error< @@ -589,11 +589,11 @@ def warn_cxx14_compat_init_statement : Warning< "%select{if|switch}0 initialization statements are incompatible with " "C++ standards before C++17">, DefaultIgnore, InGroup; def ext_for_range_init_stmt : ExtWarn< - "range-based for loop initialization statements are a C++2a extension">, - InGroup; + "range-based for loop initialization statements are a C++20 extension">, + InGroup; def warn_cxx17_compat_for_range_init_stmt : Warning< "range-based for loop initialization statements are incompatible with " - "C++ standards before C++2a">, DefaultIgnore, InGroup; + "C++ standards before C++20">, DefaultIgnore, InGroup; def warn_empty_init_statement : Warning< "empty initialization statement of '%select{if|switch|range-based for}0' " "has no effect">, InGroup, DefaultIgnore; @@ -681,13 +681,13 @@ def err_ms_property_initializer : Error< "property declaration cannot have an in-class initializer">; def warn_cxx2a_compat_explicit_bool : Warning< - "this expression will be parsed as explicit(bool) in C++2a">, - InGroup, DefaultIgnore; + "this expression will be parsed as explicit(bool) in C++20">, + InGroup, DefaultIgnore; def warn_cxx17_compat_explicit_bool : Warning< - "explicit(bool) is incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; -def ext_explicit_bool : ExtWarn<"explicit(bool) is a C++2a extension">, - InGroup; + "explicit(bool) is incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; +def ext_explicit_bool : ExtWarn<"explicit(bool) is a C++20 extension">, + InGroup; /// C++ Templates def err_expected_template : Error<"expected template">; @@ -844,11 +844,11 @@ def warn_cxx98_compat_nonstatic_member_init : Warning< "in-class initialization of non-static data members is incompatible with C++98">, InGroup, DefaultIgnore; def ext_bitfield_member_init: ExtWarn< - "default member initializer for bit-field is a C++2a extension">, - InGroup; + "default member initializer for bit-field is a C++20 extension">, + InGroup; def warn_cxx17_compat_bitfield_member_init: Warning< "default member initializer for bit-field is incompatible with " - "C++ standards before C++2a">, InGroup, DefaultIgnore; + "C++ standards before C++20">, InGroup, DefaultIgnore; def err_incomplete_array_member_init: Error< "array bound cannot be deduced from an in-class initializer">; @@ -944,13 +944,13 @@ def warn_cxx14_compat_constexpr_on_lambda : Warning< def ext_constexpr_on_lambda_cxx17 : ExtWarn< "'constexpr' on lambda expressions is a C++17 extension">, InGroup; -// C++2a template lambdas +// C++20 template lambdas def ext_lambda_template_parameter_list: ExtWarn< - "explicit template parameter list for lambdas is a C++2a extension">, - InGroup; + "explicit template parameter list for lambdas is a C++20 extension">, + InGroup; def warn_cxx17_compat_lambda_template_parameter_list: Warning< "explicit template parameter list for lambdas is incompatible with " - "C++ standards before C++2a">, InGroup, DefaultIgnore; + "C++ standards before C++20">, InGroup, DefaultIgnore; def err_lambda_template_parameter_list_empty : Error< "lambda template parameter list cannot be empty">; @@ -1415,7 +1415,7 @@ let CategoryName = "Concepts Issue" in { def err_concept_definition_not_identifier : Error< "name defined in concept definition must be an identifier">; def ext_concept_legacy_bool_keyword : ExtWarn< - "ISO C++2a does not permit the 'bool' keyword after 'concept'">, + "ISO C++20 does not permit the 'bool' keyword after 'concept'">, InGroup>; def err_placeholder_expected_auto_or_decltype_auto : Error< "expected 'auto' or 'decltype(auto)' after concept name">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 308e5f3a457ef..8d8309146ddca 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -224,10 +224,10 @@ def ext_flexible_array_init : Extension< // C++20 designated initializers def ext_cxx_designated_init : Extension< - "designated initializers are a C++20 extension">, InGroup; + "designated initializers are a C++20 extension">, InGroup; def warn_cxx17_compat_designated_init : Warning< "designated initializers are incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def ext_designated_init_mixed : ExtWarn< "mixture of designated and non-designated initializers in the same " "initializer list is a C99 extension">, InGroup; @@ -475,13 +475,13 @@ def err_decomp_decl_spec : Error< "%plural{1:'%1'|:with '%1' specifiers}0">; def ext_decomp_decl_spec : ExtWarn< "decomposition declaration declared " - "%plural{1:'%1'|:with '%1' specifiers}0 is a C++2a extension">, - InGroup; + "%plural{1:'%1'|:with '%1' specifiers}0 is a C++20 extension">, + InGroup; def warn_cxx17_compat_decomp_decl_spec : Warning< "decomposition declaration declared " "%plural{1:'%1'|:with '%1' specifiers}0 " - "is incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "is incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def err_decomp_decl_type : Error< "decomposition declaration cannot be declared with type %0; " "declared type must be 'auto' or reference to 'auto'">; @@ -2027,7 +2027,7 @@ def err_init_list_bad_dest_type : Error< "list">; def warn_cxx2a_compat_aggregate_init_with_ctors : Warning< "aggregate initialization of type %0 with user-declared constructors " - "is incompatible with C++2a">, DefaultIgnore, InGroup; + "is incompatible with C++20">, DefaultIgnore, InGroup; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to " @@ -2523,7 +2523,7 @@ def err_constexpr_redecl_mismatch : Error< def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; def warn_cxx17_compat_constexpr_virtual : Warning< "virtual constexpr functions are incompatible with " - "C++ standards before C++2a">, InGroup, DefaultIgnore; + "C++ standards before C++20">, InGroup, DefaultIgnore; def err_constexpr_virtual_base : Error< "constexpr %select{member function|constructor}0 not allowed in " "%select{struct|interface|class}1 with virtual base " @@ -2549,11 +2549,11 @@ def warn_cxx11_compat_constexpr_body_invalid_stmt : Warning< InGroup, DefaultIgnore; def ext_constexpr_body_invalid_stmt_cxx2a : ExtWarn< "use of this statement in a constexpr %select{function|constructor}0 " - "is a C++2a extension">, InGroup; + "is a C++20 extension">, InGroup; def warn_cxx17_compat_constexpr_body_invalid_stmt : Warning< "use of this statement in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "is incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def ext_constexpr_type_definition : ExtWarn< "type definition in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; @@ -2579,11 +2579,11 @@ def err_constexpr_local_var_non_literal_type : Error< "%select{function|constructor}0">; def ext_constexpr_local_var_no_init : ExtWarn< "uninitialized variable in a constexpr %select{function|constructor}0 " - "is a C++20 extension">, InGroup; + "is a C++20 extension">, InGroup; def warn_cxx17_compat_constexpr_local_var_no_init : Warning< "uninitialized variable in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def ext_constexpr_function_never_constant_expr : ExtWarn< "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a " "constant expression">, InGroup>, DefaultError; @@ -2609,29 +2609,29 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning< def note_constexpr_body_previous_return : Note< "previous return statement is here">; -// C++2a function try blocks in constexpr +// C++20 function try blocks in constexpr def ext_constexpr_function_try_block_cxx2a : ExtWarn< "function try block in constexpr %select{function|constructor}0 is " - "a C++2a extension">, InGroup; + "a C++20 extension">, InGroup; def warn_cxx17_compat_constexpr_function_try_block : Warning< "function try block in constexpr %select{function|constructor}0 is " - "incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def ext_constexpr_union_ctor_no_init : ExtWarn< "constexpr union constructor that does not initialize any member " - "is a C++20 extension">, InGroup; + "is a C++20 extension">, InGroup; def warn_cxx17_compat_constexpr_union_ctor_no_init : Warning< "constexpr union constructor that does not initialize any member " "is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def ext_constexpr_ctor_missing_init : ExtWarn< "constexpr constructor that does not initialize all members " - "is a C++20 extension">, InGroup; + "is a C++20 extension">, InGroup; def warn_cxx17_compat_constexpr_ctor_missing_init : Warning< "constexpr constructor that does not initialize all members " "is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def note_constexpr_ctor_missing_init : Note< "member not initialized by constructor">; def note_non_literal_no_constexpr_ctors : Note< @@ -2763,7 +2763,7 @@ def warn_cxx98_compat_unicode_type : Warning< InGroup, DefaultIgnore; def warn_cxx17_compat_unicode_type : Warning< "'char8_t' type specifier is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; // __make_integer_seq def err_integer_sequence_negative_length : Error< @@ -3074,6 +3074,9 @@ def err_alignment_too_big : Error< "requested alignment must be %0 or smaller">; def err_alignment_not_power_of_two : Error< "requested alignment is not a power of 2">; +def warn_alignment_not_power_of_two : Warning< + err_alignment_not_power_of_two.Text>, + InGroup>; def err_alignment_dependent_typedef_name : Error< "requested alignment is dependent but declaration is not dependent">; @@ -4390,11 +4393,11 @@ def err_template_tag_noparams : Error< def warn_cxx17_compat_adl_only_template_id : Warning< "use of function template name with no prior function template " "declaration in function call with explicit template arguments " - "is incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "is incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def ext_adl_only_template_id : ExtWarn< "use of function template name with no prior declaration in function call " - "with explicit template arguments is a C++2a extension">, InGroup; + "with explicit template arguments is a C++20 extension">, InGroup; // C++ Template Argument Lists def err_template_missing_args : Error< @@ -4536,12 +4539,12 @@ def err_pointer_to_member_oper_value_classify: Error< "pointer-to-member function type %0 can only be called on an " "%select{rvalue|lvalue}1">; def ext_pointer_to_const_ref_member_on_rvalue : Extension< - "invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">, - InGroup, SFINAEFailure; + "invoking a pointer to a 'const &' member function on an rvalue is a C++20 extension">, + InGroup, SFINAEFailure; def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning< "invoking a pointer to a 'const &' member function on an rvalue is " - "incompatible with C++ standards before C++2a">, - InGroup, DefaultIgnore; + "incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; def ext_ms_deref_template_argument: ExtWarn< "non-type template argument containing a dereference operation is a " "Microsoft extension">, InGroup; @@ -6290,7 +6293,7 @@ def err_array_init_utf8_string_into_char : Error< "UTF-8 string literal%select{ is not permitted by '-fchar8_t'|}0">; def warn_cxx2a_compat_utf8_string : Warning< "type of UTF-8 string literal will change from array of const char to " - "array of const char8_t in C++2a">, InGroup, DefaultIgnore; + "array of const char8_t in C++20">, InGroup, DefaultIgnore; def note_cxx2a_compat_utf8_string_remove_u8 : Note< "remove 'u8' prefix to avoid a change of behavior; " "Clang encodes unprefixed narrow string literals as UTF-8">; @@ -7219,9 +7222,9 @@ let CategoryName = "Lambda Issue" in { "cannot deduce type for lambda capture %0 from initializer list">; def warn_cxx17_compat_init_capture_pack : Warning< "initialized lambda capture packs are incompatible with C++ standards " - "before C++2a">, InGroup, DefaultIgnore; + "before C++20">, InGroup, DefaultIgnore; def ext_init_capture_pack : ExtWarn< - "initialized lambda pack captures are a C++2a extension">, InGroup; + "initialized lambda pack captures are a C++20 extension">, InGroup; // C++14 generic lambdas. def warn_cxx11_compat_generic_lambda : Warning< @@ -7239,23 +7242,23 @@ let CategoryName = "Lambda Issue" in { def err_parameter_shadow_capture : Error< "a lambda parameter cannot shadow an explicitly captured entity">; - // C++2a [=, this] captures. + // C++20 [=, this] captures. def warn_cxx17_compat_equals_this_lambda_capture : Warning< "explicit capture of 'this' with a capture default of '=' is incompatible " - "with C++ standards before C++2a">, InGroup, DefaultIgnore; + "with C++ standards before C++20">, InGroup, DefaultIgnore; def ext_equals_this_lambda_capture_cxx2a : ExtWarn< "explicit capture of 'this' with a capture default of '=' " - "is a C++2a extension">, InGroup; + "is a C++20 extension">, InGroup; def warn_deprecated_this_capture : Warning< "implicit capture of 'this' with a capture default of '=' is deprecated">, InGroup, DefaultIgnore; def note_deprecated_this_capture : Note< "add an explicit capture of 'this' to capture '*this' by reference">; - // C++2a default constructible / assignable lambdas. + // C++20 default constructible / assignable lambdas. def warn_cxx17_compat_lambda_def_ctor_assign : Warning< "%select{default construction|assignment}0 of lambda is incompatible with " - "C++ standards before C++2a">, InGroup, DefaultIgnore; + "C++ standards before C++20">, InGroup, DefaultIgnore; } def err_return_in_captured_stmt : Error< @@ -7405,6 +7408,21 @@ def warn_incompatible_qualified_id : Warning< "sending type to parameter of incompatible type}0,1" "|%diff{casting $ to incompatible type $|" "casting type to incompatible type}0,1}2">; +def err_incompatible_qualified_id : Error< + "%select{%diff{assigning to $ from incompatible type $|" + "assigning to type from incompatible type}0,1" + "|%diff{passing $ to parameter of incompatible type $|" + "passing type to parameter of incompatible type}0,1" + "|%diff{returning $ from a function with incompatible result type $|" + "returning type from a function with incompatible result type}0,1" + "|%diff{converting $ to incompatible type $|" + "converting type to incompatible type}0,1" + "|%diff{initializing $ with an expression of incompatible type $|" + "initializing type with an expression of incompatible type}0,1" + "|%diff{sending $ to parameter of incompatible type $|" + "sending type to parameter of incompatible type}0,1" + "|%diff{casting $ to incompatible type $|" + "casting type to incompatible type}0,1}2">; def ext_typecheck_convert_pointer_int : ExtWarn< "incompatible pointer to integer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7423,6 +7441,23 @@ def ext_typecheck_convert_pointer_int : ExtWarn< "; remove *|" "; remove &}3">, InGroup; +def err_typecheck_convert_pointer_int : Error< + "incompatible pointer to integer conversion " + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7441,6 +7476,23 @@ def ext_typecheck_convert_int_pointer : ExtWarn< "; remove *|" "; remove &}3">, InGroup, SFINAEFailure; +def err_typecheck_convert_int_pointer : Error< + "incompatible integer to pointer conversion " + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">; def ext_typecheck_convert_pointer_void_func : Extension< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" @@ -7454,6 +7506,19 @@ def ext_typecheck_convert_pointer_void_func : Extension< "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " converts between void pointer and function pointer">; +def err_typecheck_convert_pointer_void_func : Error< + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " converts between void pointer and function pointer">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" @@ -7468,6 +7533,19 @@ def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< "|%diff{casting $ to type $|casting between types}0,1}2" " converts between pointers to integer types with different sign">, InGroup>; +def err_typecheck_convert_incompatible_pointer_sign : Error< + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " converts between pointers to integer types with different sign">; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7486,6 +7564,23 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn< "; remove *|" "; remove &}3">, InGroup; +def err_typecheck_convert_incompatible_pointer : Error< + "incompatible pointer types " + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">; def ext_typecheck_convert_incompatible_function_pointer : ExtWarn< "incompatible function pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7504,6 +7599,23 @@ def ext_typecheck_convert_incompatible_function_pointer : ExtWarn< "; remove *|" "; remove &}3">, InGroup; +def err_typecheck_convert_incompatible_function_pointer : Error< + "incompatible function pointer types " + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" @@ -7518,6 +7630,19 @@ def ext_typecheck_convert_discards_qualifiers : ExtWarn< "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers">, InGroup; +def err_typecheck_convert_discards_qualifiers : Error< + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " discards qualifiers">; def ext_nested_pointer_qualifier_mismatch : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" @@ -7532,6 +7657,19 @@ def ext_nested_pointer_qualifier_mismatch : ExtWarn< "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers in nested pointer types">, InGroup; +def err_nested_pointer_qualifier_mismatch : Error< + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " discards qualifiers in nested pointer types">; def warn_incompatible_vectors : Warning< "incompatible vector types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7546,6 +7684,19 @@ def warn_incompatible_vectors : Warning< "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2">, InGroup, DefaultIgnore; +def err_incompatible_vectors : Error< + "incompatible vector types " + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2">; def err_int_to_block_pointer : Error< "invalid block pointer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" @@ -7956,7 +8107,7 @@ def ext_cxx14_attr : Extension< def ext_cxx17_attr : Extension< "use of the %0 attribute is a C++17 extension">, InGroup; def ext_cxx2a_attr : Extension< - "use of the %0 attribute is a C++2a extension">, InGroup; + "use of the %0 attribute is a C++20 extension">, InGroup; def warn_unused_comparison : Warning< "%select{equality|inequality|relational|three-way}0 comparison result unused">, @@ -7970,7 +8121,7 @@ def err_incomplete_type_used_in_type_trait_expr : Error< // C++20 constinit and require_constant_initialization attribute def warn_cxx20_compat_constinit : Warning< "'constinit' specifier is incompatible with C++ standards before C++20">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def err_constinit_local_variable : Error< "local variable cannot be declared 'constinit'">; def err_require_constant_init_failed : Error< @@ -8425,7 +8576,7 @@ def note_deleted_type_mismatch : Note< def warn_cxx17_compat_defaulted_method_type_mismatch : Warning< "explicitly defaulting this %sub{select_special_member_kind}0 with a type " "different from the implicit type is incompatible with C++ standards before " - "C++2a">, InGroup, DefaultIgnore; + "C++20">, InGroup, DefaultIgnore; def warn_vbase_moved_multiple_times : Warning< "defaulted move assignment operator of %0 will move assign virtual base " "class %1 multiple times">, InGroup>; @@ -8439,10 +8590,10 @@ def select_defaulted_comparison_kind : TextSubstitution< "%select{|equality|three-way|equality|relational}0 comparison " "operator">; def ext_defaulted_comparison : ExtWarn< - "defaulted comparison operators are a C++20 extension">, InGroup; + "defaulted comparison operators are a C++20 extension">, InGroup; def warn_cxx17_compat_defaulted_comparison : Warning< "defaulted comparison operators are incompatible with C++ standards " - "before C++20">, InGroup, DefaultIgnore; + "before C++20">, InGroup, DefaultIgnore; def err_defaulted_comparison_template : Error< "comparison operator template cannot be defaulted">; def err_defaulted_comparison_out_of_class : Error< @@ -10475,7 +10626,7 @@ def err_sycl_kernel_name_class_not_top_level : Error< "nest in a namespace: %0">; def err_sycl_restrict : Error< "SYCL kernel cannot " -"%select{use a global variable" +"%select{use a non-const global variable" "|use rtti" "|use a non-const static data variable" "|call a virtual function" diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 28eb694ba9a89..20e1b141a3ef9 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -252,6 +252,7 @@ EXTENSION(overloadable_unmarked, true) EXTENSION(pragma_clang_attribute_namespaces, true) EXTENSION(pragma_clang_attribute_external_declaration, true) EXTENSION(gnu_asm, LangOpts.GNUAsm) +EXTENSION(gnu_asm_goto_with_outputs, LangOpts.GNUAsm) #undef EXTENSION #undef FEATURE diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def index 427691fb71e94..7f1a24db7e9be 100644 --- a/clang/include/clang/Basic/LangStandards.def +++ b/clang/include/clang/Basic/LangStandards.def @@ -140,15 +140,17 @@ LANGSTANDARD(gnucxx17, "gnu++17", Digraphs | HexFloat | GNUMode) LANGSTANDARD_ALIAS_DEPR(gnucxx17, "gnu++1z") -LANGSTANDARD(cxx2a, "c++2a", - CXX, "Working draft for ISO C++ 2020", +LANGSTANDARD(cxx20, "c++20", + CXX, "ISO C++ 2020 DIS", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | CPlusPlus2a | Digraphs | HexFloat) +LANGSTANDARD_ALIAS_DEPR(cxx20, "c++2a") -LANGSTANDARD(gnucxx2a, "gnu++2a", - CXX, "Working draft for ISO C++ 2020 with GNU extensions", +LANGSTANDARD(gnucxx20, "gnu++20", + CXX, "ISO C++ 2020 DIS with GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | CPlusPlus2a | Digraphs | HexFloat | GNUMode) +LANGSTANDARD_ALIAS_DEPR(gnucxx20, "gnu++2a") // OpenCL LANGSTANDARD(opencl10, "cl1.0", diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 41923cddc4930..2333202968198 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -162,7 +162,7 @@ def CoawaitExpr : StmtNode; def DependentCoawaitExpr : StmtNode; def CoyieldExpr : StmtNode; -// C++2a Concepts expressions +// C++20 Concepts expressions def ConceptSpecializationExpr : StmtNode; def RequiresExpr : StmtNode; diff --git a/clang/include/clang/Basic/TargetCXXABI.h b/clang/include/clang/Basic/TargetCXXABI.h index 1ab45d2ce9a1e..93f70fc70dd87 100644 --- a/clang/include/clang/Basic/TargetCXXABI.h +++ b/clang/include/clang/Basic/TargetCXXABI.h @@ -109,6 +109,13 @@ class TargetCXXABI { /// - constructors and destructors return 'this', as in ARM. Fuchsia, + /// The XL ABI is the ABI used by IBM xlclang compiler and is a modified + /// version of the Itanium ABI. + /// + /// The relevant changes from the Itanium ABI are: + /// - static initialization is adjusted to use sinit and sterm functions; + XL, + /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and /// compatible compilers). /// @@ -148,6 +155,7 @@ class TargetCXXABI { case WatchOS: case GenericMIPS: case WebAssembly: + case XL: return true; case Microsoft: @@ -168,6 +176,7 @@ class TargetCXXABI { case WatchOS: case GenericMIPS: case WebAssembly: + case XL: return false; case Microsoft: @@ -202,6 +211,7 @@ class TargetCXXABI { case iOS64: case WatchOS: case Microsoft: + case XL: return true; } llvm_unreachable("bad ABI kind"); @@ -278,6 +288,7 @@ class TargetCXXABI { case iOS: // old iOS compilers did not follow this rule case Microsoft: case GenericMIPS: + case XL: return true; } llvm_unreachable("bad ABI kind"); @@ -315,6 +326,7 @@ class TargetCXXABI { case GenericARM: case iOS: case GenericMIPS: + case XL: return UseTailPaddingUnlessPOD03; // iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 4edef930f3b4c..7150852d70040 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -43,6 +43,12 @@ def vqaddq: Intrinsic $a, $b)>; def vqsubq: Intrinsic $a, $b)>; +let pnt = PNT_NType in { + def vqaddq_n: Intrinsic:$b), + (IRIntBase<"sadd_sat", [Vector]> $a, (splat $b))>; + def vqsubq_n: Intrinsic:$b), + (IRIntBase<"ssub_sat", [Vector]> $a, (splat $b))>; +} } let params = T.Unsigned in { def vqaddq_u: Intrinsic $a, $b)>, NameOverride<"vqsubq">; +let pnt = PNT_NType in { + def vqaddq_u_n: Intrinsic:$b), + (IRIntBase<"uadd_sat", [Vector]> $a, (splat $b))>, + NameOverride<"vqaddq_n">; + def vqsubq_u_n: Intrinsic:$b), + (IRIntBase<"usub_sat", [Vector]> $a, (splat $b))>, + NameOverride<"vqsubq_n">; +} } // Some intrinsics below are implemented not as IR fragments, but as @@ -85,12 +99,32 @@ def vmullbq_int: Intrinsic $a, $b, (unsignedflag Scalar), 1)>; +let pnt = PNT_NType in { + def vaddq_n: Intrinsic:$b), + (add $a, (splat $b))>; + def vsubq_n: Intrinsic:$b), + (sub $a, (splat $b))>; + def vmulq_n: Intrinsic:$b), + (mul $a, (splat $b))>; + def vhaddq_n: Intrinsic:$b), + (IRInt<"vhadd", [Vector]> $a, (splat $b), + (unsignedflag Scalar))>; + def vhsubq_n: Intrinsic:$b), + (IRInt<"vhsub", [Vector]> $a, (splat $b), + (unsignedflag Scalar))>; +} } let params = T.Signed in { def vqdmulhq: Intrinsic $a, $b)>; def vqrdmulhq: Intrinsic $a, $b)>; +let pnt = PNT_NType in { + def vqdmulhq_n: Intrinsic:$b), + (IRInt<"vqdmulh", [Vector]> $a, (splat $b))>; + def vqrdmulhq_n: Intrinsic:$b), + (IRInt<"vqrdmulh", [Vector]> $a, (splat $b))>; +} } let params = T.Poly, overrideKindLetter = "p" in { @@ -114,6 +148,18 @@ def vsubqf: Intrinsic, NameOverride<"vsubq">; def vmulqf: Intrinsic, NameOverride<"vmulq">; + +let pnt = PNT_NType in { + def vaddqf_n: Intrinsic:$b), + (fadd $a, (splat $b))>, + NameOverride<"vaddq_n">; + def vsubqf_n: Intrinsic:$b), + (fsub $a, (splat $b))>, + NameOverride<"vsubq_n">; + def vmulqf_n: Intrinsic:$b), + (fmul $a, (splat $b))>, + NameOverride<"vmulq_n">; +} } let params = !listconcat(T.Int16, T.Int32) in { @@ -188,6 +234,36 @@ let params = T.Unsigned in { defm vdwdup: vxdup_mc<(? u32:$limit, imm_1248:$step), (? $limit, $step)>; } +let params = T.Int in { + def vmvnq: Intrinsic; + def vclzq: Intrinsic $a, (i1 0))>; +} +let params = T.Signed in { + def vclsq: Intrinsic $a)>; + def vnegq: Intrinsic; + def vabsq: Intrinsic; + def vqnegq: Intrinsic; + def vqabsq: Intrinsic; +} +let params = T.Float in { + def vnegq_f: Intrinsic, + NameOverride<"vnegq">; + def vabsq_f: Intrinsic $a)>, NameOverride<"vabsq">; +} + // The bitcasting below is not overcomplicating the IR because while // Vector and UVector may be different vector types at the C level i.e. // vectors of same size signed/unsigned ints. Once they're lowered @@ -217,6 +293,16 @@ multiclass VectorVectorArithmetic; } +multiclass VectorScalarArithmetic { + defm "" : IntrinsicMXNameOverride< + Vector, (args Vector:$a, unpromoted:$b, Predicate:$pred), + !con((IRInt $a, (splat $b)), + extraArgs, (? $pred, $inactive)), basename, wantXVariant, "_n", + PNT_NType, PNT_NType>; +} + multiclass VectorVectorArithmeticBitcast { defm "" : IntrinsicMX; defm vornq : VectorVectorArithmeticBitcast<"orn_predicated">; defm vorrq : VectorVectorArithmeticBitcast<"orr_predicated">; + + defm : VectorScalarArithmetic<"add_predicated", "vaddq">; + defm : VectorScalarArithmetic<"sub_predicated", "vsubq">; + defm : VectorScalarArithmetic<"mul_predicated", "vmulq">; } -multiclass DblVectorVectorArithmetic { +multiclass DblVectorVectorArithmetic { defm "" : IntrinsicMX< - DblVector, (args Vector:$a, Vector:$b, Predicate:$pred), - !con((IRInt $a, $b), - extraArgs, (? $pred, $inactive))>; + DblVector, (args Vector:$a, Vector:$b, DblPredicate:$pred), + !con((IRInt $a, $b), + extraArgs, (? $pred, $inactive)), wantXVariant>; +} + +multiclass DblVectorScalarArithmetic { + defm "" : IntrinsicMXNameOverride< + DblVector, (args Vector:$a, unpromoted:$b, DblPredicate:$pred), + !con((IRInt $a, (splat $b)), + extraArgs, (? $pred, $inactive)), basename, wantXVariant, "_n", + PNT_NType, PNT_NType>; } // Predicated intrinsics - Int types only @@ -260,6 +361,11 @@ let params = T.Int in { defm vhsubq : VectorVectorArithmetic<"hsub_predicated", (? (unsignedflag Scalar))>; defm vmullbq_int : DblVectorVectorArithmetic<"mull_int_predicated", (? (unsignedflag Scalar), (u32 0))>; defm vmulltq_int : DblVectorVectorArithmetic<"mull_int_predicated", (? (unsignedflag Scalar), (u32 1))>; + + defm : VectorScalarArithmetic<"qadd_predicated", "vqaddq", (? (unsignedflag Scalar)), 0>; + defm : VectorScalarArithmetic<"hadd_predicated", "vhaddq", (? (unsignedflag Scalar))>; + defm : VectorScalarArithmetic<"qsub_predicated", "vqsubq", (? (unsignedflag Scalar)), 0>; + defm : VectorScalarArithmetic<"hsub_predicated", "vhsubq", (? (unsignedflag Scalar))>; } let params = T.Signed in { defm vqdmulhq : VectorVectorArithmetic<"qdmulh_predicated", (?), 0>; @@ -268,6 +374,9 @@ let params = T.Signed in { (IRInt<"vmina_predicated", [UVector,Predicate]> $a, $b, $pred)>; def vmaxaq_m: Intrinsic $a, $b, $pred)>; + + defm : VectorScalarArithmetic<"qdmulh_predicated", "vqdmulhq", (?), 0>; + defm : VectorScalarArithmetic<"qrdmulh_predicated", "vqrdmulhq", (?), 0>; } let params = T.Poly, overrideKindLetter = "p" in { @@ -275,6 +384,28 @@ let params = T.Poly, overrideKindLetter = "p" in { defm vmulltq_poly : DblVectorVectorArithmetic<"mull_poly_predicated", (? (u32 1))>; } +let params = [s16, s32] in { + def vqdmullbq: Intrinsic $a, $b, 0)>; + def vqdmulltq: Intrinsic $a, $b, 1)>; + defm vqdmullbq: DblVectorVectorArithmetic<"vqdmull_predicated", (? (u32 0)), 0>; + defm vqdmulltq: DblVectorVectorArithmetic<"vqdmull_predicated", (? (u32 1)), 0>; + + let pnt = PNT_NType in { + def vqdmullbq_n: Intrinsic:$b), + (IRInt<"vqdmull", [DblVector, Vector]> + $a, (splat $b), 0)>; + def vqdmulltq_n: Intrinsic:$b), + (IRInt<"vqdmull", [DblVector, Vector]> + $a, (splat $b), 1)>; + } + defm vqdmullbq_n: DblVectorScalarArithmetic<"vqdmull_predicated", + "vqdmullbq", (? (u32 0)), 0>; + defm vqdmulltq_n: DblVectorScalarArithmetic<"vqdmull_predicated", + "vqdmulltq", (? (u32 1)), 0>; +} + // Predicated intrinsics - Float types only let params = T.Float in { defm vminnmq : VectorVectorArithmetic<"min_predicated", (? (u32 0))>; @@ -305,6 +436,53 @@ foreach half = [ "b", "t" ] in { } // params = [f32], pnt = PNT_None } // loop over half = "b", "t" +multiclass float_int_conversions { + defvar FVector = VecOf; + defvar IVector = VecOf; + + let params = [IScalar], pnt = PNT_2Type in + def : Intrinsic, + NameOverride<"vcvtq_" # FScalar>; + let params = [FScalar], pnt = PNT_None in + def : Intrinsic, + NameOverride<"vcvtq_" # IScalar>; +} + +defm : float_int_conversions; +defm : float_int_conversions; +defm : float_int_conversions; +defm : float_int_conversions; + +let params = [s8, u8, s16, u16] in { + def vmovlbq: Intrinsic; + def vmovltq: Intrinsic; +} + +let params = [s16, u16, s32, u32] in { + def vmovnbq: Intrinsic; + def vmovntq: Intrinsic; +} + +let params = T.Float in { + def vrndq: Intrinsic $a)>; + def vrndmq: Intrinsic $a)>; + def vrndpq: Intrinsic $a)>; + def vrndaq: Intrinsic $a)>; + def vrndxq: Intrinsic $a)>; + def vrndnq: Intrinsic $a)>; +} + multiclass compare_with_pred { // Make the predicated and unpredicated versions of a single comparison. @@ -736,8 +914,8 @@ multiclass vshll_imm { (IRInt<"vshll_imm", [DblVector, Vector]> $v, $sh, (unsignedflag Scalar), top)>; defm "": IntrinsicMX + DblPredicate:$pred), + (IRInt<"vshll_imm_predicated", [DblVector, Vector, DblPredicate]> $v, $sh, (unsignedflag Scalar), top, $pred, $inactive), 1, "_n">; } } @@ -1053,6 +1231,13 @@ defm vrmlsldavh : MVEBinaryVectorHoriz64R; defm vrmlsldavh : MVEBinaryVectorHoriz64R; } +let params = T.All8 in +def vrev16q : Intrinsic; +let params = !listconcat(T.All8, T.All16) in +def vrev32q : Intrinsic; +let params = T.Usual in +def vrev64q : Intrinsic; + foreach desttype = T.All in { // We want a vreinterpretq between every pair of supported vector types // _except_ that there shouldn't be one from a type to itself. @@ -1124,3 +1309,13 @@ foreach desttype = !listconcat(T.Int16, T.Int32, T.Float) in { 1, "_n_"#desttype, PNT_2Type, pnt_nx>; } } + +let params = T.Usual in { +let pnt = PNT_NType in +def vbrsrq_n: Intrinsic $a, $b)>; +defm vbrsrq : IntrinsicMX + $inactive, $a, $b, $pred), 1, "_n", + PNT_NType, PNT_NType>; +} diff --git a/clang/include/clang/Basic/arm_mve_defs.td b/clang/include/clang/Basic/arm_mve_defs.td index 2a462974bb12d..776dc9c73da42 100644 --- a/clang/include/clang/Basic/arm_mve_defs.td +++ b/clang/include/clang/Basic/arm_mve_defs.td @@ -98,6 +98,9 @@ def extend: CGHelperFn<"SignOrZeroExtend"> { let special_params = [IRBuilderIntParam<2, "bool">]; } def zeroinit: IRFunction<"llvm::Constant::getNullValue">; +def int_min: CGHelperFn<"ARMMVEConstantSplat<1,0>">; +def int_max: CGHelperFn<"ARMMVEConstantSplat<0,1>">; +def uint_max: CGHelperFn<"ARMMVEConstantSplat<1,1>">; def undef: IRFunction<"UndefValue::get">; def icmp_eq: IRBuilder<"CreateICmpEQ">; def icmp_ne: IRBuilder<"CreateICmpNE">; @@ -117,6 +120,24 @@ def fcmp_lt: IRBuilder<"CreateFCmpOLT">; def fcmp_le: IRBuilder<"CreateFCmpOLE">; def splat: CGHelperFn<"ARMMVEVectorSplat">; def select: IRBuilder<"CreateSelect">; +def fneg: IRBuilder<"CreateFNeg">; +def sitofp: IRBuilder<"CreateSIToFP">; +def uitofp: IRBuilder<"CreateUIToFP">; +def fptosi: IRBuilder<"CreateFPToSI">; +def fptoui: IRBuilder<"CreateFPToUI">; +def vrev: CGHelperFn<"ARMMVEVectorElementReverse"> { + let special_params = [IRBuilderIntParam<1, "unsigned">]; +} +def unzip: CGHelperFn<"VectorUnzip"> { + let special_params = [IRBuilderIntParam<1, "bool">]; +} +def zip: CGHelperFn<"VectorZip">; + +// Helper for making boolean flags in IR +def i1: IRBuilderBase { + let prefix = "llvm::ConstantInt::get(Builder.getInt1Ty(), "; + let special_params = [IRBuilderIntParam<0, "bool">]; +} // A node that makes an Address out of a pointer-typed Value, by // providing an alignment as the second argument. @@ -167,6 +188,10 @@ def seq; // and 0 for a signed (or floating) one. def unsignedflag; +// 'bitsize' also takes a scalar type, and expands into an integer +// constant giving its size in bits. +def bitsize; + // If you put CustomCodegen<"foo"> in an intrinsic's codegen field, it // indicates that the IR generation for that intrinsic is done by handwritten // C++ and not autogenerated at all. The effect in the MVE builtin codegen @@ -293,9 +318,11 @@ def SScalar: Signed; def SVector: VecOf; // DblVector expands to a vector of scalars of size twice the size of Scalar. +// DblPredicate expands to a predicate corresponding to DblVector // HalfVector, similarly, expands to a vector of half-sized scalars. And // UHalfVector is a vector of half-sized _unsigned integers_. def DblVector: VecOf>; +def DblPredicate: PredOf>; def HalfVector: VecOf>; def UHalfVector: VecOf>>; @@ -495,6 +522,29 @@ multiclass IntrinsicMX { + def "_m" # nameSuffix: + Intrinsic, + NameOverride { + let pnt = pnt_m; + } + + foreach unusedVar = !if(!eq(wantXVariant, 1), [1], []) in { + def "_x" # nameSuffix: + Intrinsic, + NameOverride { + let pnt = pnt_x; + } + } +} + + // ----------------------------------------------------------------------------- // Convenience lists of parameter types. 'T' is just a container record, so you // can define a typical intrinsic with 'let Params = T.Usual', or similar, diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 42fc1315d85e8..3f223609f3f8d 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -284,8 +284,6 @@ def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">, HelpText<"Enable enhanced struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; -def mcode_model : Separate<["-"], "mcode-model">, - HelpText<"The code model to use">, Values<"tiny,small,kernel,medium,large">; def mdebug_pass : Separate<["-"], "mdebug-pass">, HelpText<"Enable additional debug output">; def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">, diff --git a/clang/include/clang/Driver/CLCompatOptions.td b/clang/include/clang/Driver/CLCompatOptions.td index 561746d931ed3..17d248a3c5ad9 100644 --- a/clang/include/clang/Driver/CLCompatOptions.td +++ b/clang/include/clang/Driver/CLCompatOptions.td @@ -156,8 +156,9 @@ def _SLASH_Qvec : CLFlag<"Qvec">, def _SLASH_Qvec_ : CLFlag<"Qvec-">, HelpText<"Disable the loop vectorization passes">, Alias; def _SLASH_showIncludes : CLFlag<"showIncludes">, - HelpText<"Print info about included files to stderr">, - Alias; + HelpText<"Print info about included files to stderr">; +def _SLASH_showIncludes_user : CLFlag<"showIncludes:user">, + HelpText<"Like /showIncludes but omit system headers">; def _SLASH_showFilenames : CLFlag<"showFilenames">, HelpText<"Print the name of each compiled file">; def _SLASH_showFilenames_ : CLFlag<"showFilenames-">, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1b5dd5971a166..73183d3ca1a49 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2011,10 +2011,10 @@ def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags< def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group; def ffunction_sections : Flag<["-"], "ffunction-sections">, Group, Flags<[CC1Option]>, - HelpText<"Place each function in its own section (ELF Only)">; + HelpText<"Place each function in its own section">; def fno_function_sections : Flag<["-"], "fno-function-sections">, Group; def fdata_sections : Flag <["-"], "fdata-sections">, Group, - Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">; + Flags<[CC1Option]>, HelpText<"Place each data in its own section">; def fno_data_sections : Flag <["-"], "fno-data-sections">, Group; def fstack_size_section : Flag<["-"], "fstack-size-section">, Group, Flags<[CC1Option]>, HelpText<"Emit section containing metadata on function stack sizes">; @@ -2023,7 +2023,7 @@ def fno_stack_size_section : Flag<["-"], "fno-stack-size-section">, Group, Group, - HelpText<"Use unique names for text and data sections (ELF Only)">; + HelpText<"Use unique names for text and data sections">; def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">, Group, Flags<[CC1Option]>; @@ -2225,10 +2225,13 @@ def mno_iamcu : Flag<["-"], "mno-iamcu">, Group, Flags<[DriverOption, C def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group; def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group; def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group; -def malign_branch_EQ : CommaJoined<["-"], "malign-branch=">, Group; -def malign_branch_boundary_EQ : Joined<["-"], "malign-branch-boundary=">, Group; +def malign_branch_EQ : CommaJoined<["-"], "malign-branch=">, Group, Flags<[DriverOption]>, + HelpText<"Specify types of branches to align">; +def malign_branch_boundary_EQ : Joined<["-"], "malign-branch-boundary=">, Group, Flags<[DriverOption]>, + HelpText<"Specify the boundary's size to align branches">; def malign_branch_prefix_size_EQ : Joined<["-"], "malign-branch-prefix-size=">, Group; -def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundaries">, Flags<[DriverOption]>, Group; +def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundaries">, Flags<[DriverOption]>, Group, + HelpText<"Align selected branches (fused, jcc, jmp) within 32-byte boundary">; def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group; def mlong_calls : Flag<["-"], "mlong-calls">, Group, HelpText<"Generate branches with extended addressability, usually via indirect jumps.">; @@ -2260,7 +2263,7 @@ def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-versio def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias; def march_EQ : Joined<["-"], "march=">, Group, Flags<[CoreOption]>; def masm_EQ : Joined<["-"], "masm=">, Group, Flags<[DriverOption]>; -def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group; +def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group, Flags<[CC1Option]>; def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group, Flags<[DriverOption, CC1Option]>, HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): " "12 (for 4KB) | 24 (for 16MB, default) | 32 (for 4GB) | 48 (for 256TB, needs -mcmodel=large)">; @@ -3384,9 +3387,6 @@ defm strength_reduce : defm tls_model : BooleanFFlag<"tls-model">, Group; defm tracer : BooleanFFlag<"tracer">, Group; defm tree_dce : BooleanFFlag<"tree-dce">, Group; -defm tree_loop_im : BooleanFFlag<"tree_loop_im">, Group; -defm tree_loop_ivcanon : BooleanFFlag<"tree_loop_ivcanon">, Group; -defm tree_loop_linear : BooleanFFlag<"tree_loop_linear">, Group; defm tree_salias : BooleanFFlag<"tree-salias">, Group; defm tree_ter : BooleanFFlag<"tree-ter">, Group; defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group; diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index a935851d5b606..4a6e293b7ffb5 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -515,7 +515,7 @@ class CompilerInstance : public ModuleLoader { /// { IntrusiveRefCntPtr getASTReader() const; - void setModuleManager(IntrusiveRefCntPtr Reader); + void setASTReader(IntrusiveRefCntPtr Reader); std::shared_ptr getModuleDepCollector() const; void setModuleDepCollector( @@ -781,7 +781,6 @@ class CompilerInstance : public ModuleLoader { return std::move(OutputStream); } - // Create module manager. void createASTReader(); bool loadModuleFile(StringRef FileName); diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c8d112054b478..ebf5468ac1fca 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1113,7 +1113,8 @@ class Parser : public CodeCompletionHandler { /// it (unless StopBeforeMatch is specified). Because we cannot guarantee /// that the token will ever occur, this skips to the next token, or to some /// likely good stopping point. If Flags has StopAtSemi flag, skipping will - /// stop at a ';' character. + /// stop at a ';' character. Balances (), [], and {} delimiter tokens while + /// skipping. /// /// If SkipUntil finds the specified token, it returns true, otherwise it /// returns false. @@ -2442,6 +2443,10 @@ class Parser : public CodeCompletionHandler { TPResult TryParseBracketDeclarator(); TPResult TryConsumeDeclarationSpecifier(); + /// Try to skip a possibly empty sequence of 'attribute-specifier's without + /// full validation of the syntactic structure of attributes. + bool TrySkipAttributes(); + public: TypeResult ParseTypeName(SourceRange *Range = nullptr, DeclaratorContext Context diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4b425d155203c..078438fa23320 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -22,8 +22,8 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/LocInfoType.h" @@ -34,6 +34,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/BitmaskEnum.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenMPKinds.h" @@ -1586,12 +1587,6 @@ class Sema final { void emitAndClearUnusedLocalTypedefWarnings(); - // Emit all deferred diagnostics. - void emitDeferredDiags(); - // Emit any deferred diagnostics for FD and erase them from the map in which - // they're stored. - void emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack); - enum TUFragmentKind { /// The global module fragment, between 'module;' and a module-declaration. Global, @@ -3822,8 +3817,7 @@ class Sema final { TemplateDiscarded, // Discarded due to uninstantiated templates Unknown, }; - FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl, - bool Final = false); + FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl); // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check. bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee); @@ -9715,6 +9709,10 @@ class Sema final { void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max); + /// addSYCLIntelPipeIOAttr - Adds a pipe I/O attribute to a particular + /// declaration. + void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID); + bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type); //===--------------------------------------------------------------------===// @@ -9837,10 +9835,22 @@ class Sema final { /// Pop OpenMP function region for non-capturing function. void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI); + /// Check whether we're allowed to call Callee from the current function. + void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckForDelayedContext = true); + + /// Check whether we're allowed to call Callee from the current function. + void checkOpenMPHostFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckCaller = true); + /// Check if the expression is allowed to be used in expressions for the /// OpenMP devices. void checkOpenMPDeviceExpr(const Expr *E); + /// Finishes analysis of the deferred functions calls that may be declared as + /// host/nohost during device/host compilation. + void finalizeOpenMPDelayedAnalysis(); + /// Checks if a type or a declaration is disabled due to the owning extension /// being disabled, and emits diagnostic messages if it is disabled. /// \param D type or declaration to be checked. @@ -10023,11 +10033,6 @@ class Sema final { void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc = SourceLocation()); - /// Finishes analysis of the deferred functions calls that may be declared as - /// host/nohost during device/host compilation. - void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, - const FunctionDecl *Callee, - SourceLocation Loc); /// Return true inside OpenMP declare target region. bool isInOpenMPDeclareTargetContext() const { return DeclareTargetNestingLevel > 0; @@ -10834,6 +10839,11 @@ class Sema final { /// are not compatible, but we accept them as an extension. IncompatiblePointer, + /// IncompatibleFunctionPointer - The assignment is between two function + /// pointers types that are not compatible, but we accept them as an + /// extension. + IncompatibleFunctionPointer, + /// IncompatiblePointerSign - The assignment is between two pointers types /// which point to integers which have a different sign, but are otherwise /// identical. This is a subset of the above, but broken out because it's by @@ -11376,6 +11386,18 @@ class Sema final { /* Caller = */ FunctionDeclAndLoc> DeviceKnownEmittedFns; + /// A partial call graph maintained during CUDA/OpenMP device code compilation + /// to support deferred diagnostics. + /// + /// Functions are only added here if, at the time they're considered, they are + /// not known-emitted. As soon as we discover that a function is + /// known-emitted, we remove it and everything it transitively calls from this + /// set and add those functions to DeviceKnownEmittedFns. + llvm::DenseMap, + /* Callees = */ llvm::MapVector, + SourceLocation>> + DeviceCallGraph; + /// Diagnostic builder for CUDA/OpenMP devices errors which may or may not be /// deferred. /// @@ -11450,6 +11472,14 @@ class Sema final { llvm::Optional PartialDiagId; }; + /// Indicate that this function (and thus everything it transtively calls) + /// will be codegen'ed, and emit any deferred diagnostics on this function and + /// its (transitive) callees. + void markKnownEmitted( + Sema &S, FunctionDecl *OrigCaller, FunctionDecl *OrigCallee, + SourceLocation OrigLoc, + const llvm::function_ref IsKnownEmitted); + /// Creates a DeviceDiagBuilder that emits the diagnostic if the current context /// is "used as device code". /// @@ -12290,8 +12320,78 @@ class Sema final { /// if (getLangOpts().SYCLIsDevice) /// SYCLDiagIfDeviceCode(Loc, diag::err_thread_unsupported); DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); + + /// Checks if Callee function is a device function and emits + /// diagnostics if it is known that it is a device function, adds this + /// function to the DeviceCallGraph otherwise. + void checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee); }; +template +void Sema::AddOneConstantValueAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *E) { + AttrType TmpAttr(Context, CI, E); + + if (!E->isValueDependent()) { + ExprResult ICE; + if (checkRangedIntegralArgument(E, &TmpAttr, ICE)) + return; + E = ICE.get(); + } + + if (IntelFPGAPrivateCopiesAttr::classof(&TmpAttr)) { + if (!D->hasAttr()) + D->addAttr(IntelFPGAMemoryAttr::CreateImplicit( + Context, IntelFPGAMemoryAttr::Default)); + } + + D->addAttr(::new (Context) AttrType(Context, CI, E)); +} + +template +void Sema::AddOneConstantPowerTwoValueAttr(Decl *D, + const AttributeCommonInfo &CI, + Expr *E) { + AttrType TmpAttr(Context, CI, E); + + if (!E->isValueDependent()) { + ExprResult ICE; + if (checkRangedIntegralArgument(E, &TmpAttr, ICE)) + return; + Expr::EvalResult Result; + E->EvaluateAsInt(Result, Context); + llvm::APSInt Value = Result.Val.getInt(); + if (!Value.isPowerOf2()) { + Diag(CI.getLoc(), diag::err_attribute_argument_not_power_of_two) + << &TmpAttr; + return; + } + if (IntelFPGANumBanksAttr::classof(&TmpAttr)) { + if (auto *BBA = D->getAttr()) { + unsigned NumBankBits = BBA->args_size(); + if (NumBankBits != Value.ceilLogBase2()) { + Diag(TmpAttr.getLocation(), diag::err_bankbits_numbanks_conflicting); + return; + } + } + } + E = ICE.get(); + } + + if (!D->hasAttr()) + D->addAttr(IntelFPGAMemoryAttr::CreateImplicit( + Context, IntelFPGAMemoryAttr::Default)); + + // We are adding a user NumBanks, drop any implicit default. + if (IntelFPGANumBanksAttr::classof(&TmpAttr)) { + if (auto *NBA = D->getAttr()) + if (NBA->isImplicit()) + D->dropAttr(); + } + + D->addAttr(::new (Context) AttrType(Context, CI, E)); +} + /// RAII object that enters a new expression evaluation context. class EnterExpressionEvaluationContext { Sema &Actions; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 76cf92af91132..91c0fc88f6e7b 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -71,6 +71,9 @@ def InsecureAPI : Package<"insecureAPI">, ParentPackage; def SecurityAlpha : Package<"security">, ParentPackage; def Taint : Package<"taint">, ParentPackage; +def CERT : Package<"cert">, ParentPackage; +def POS : Package<"pos">, ParentPackage; + def Unix : Package<"unix">; def UnixAlpha : Package<"unix">, ParentPackage; def CString : Package<"cstring">, ParentPackage; @@ -829,6 +832,15 @@ def FloatLoopCounter : Checker<"FloatLoopCounter">, } // end "security" +let ParentPackage = POS in { + + def PutenvWithAuto : Checker<"34c">, + HelpText<"Finds calls to the 'putenv' function which pass a pointer to " + "an automatic variable as the argument.">, + Documentation; + +} // end "alpha.cert.pos" + let ParentPackage = SecurityAlpha in { def ArrayBoundChecker : Checker<"ArrayBound">, diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index 22c1a7dd98ccb..637b89fd90361 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -11,16 +11,16 @@ // Common strings used for the "category" of many static analyzer issues. namespace clang { - namespace ento { - namespace categories { - extern const char * const CoreFoundationObjectiveC; - extern const char * const LogicError; - extern const char * const MemoryRefCount; - extern const char * const MemoryError; - extern const char * const UnixAPI; - extern const char * const CXXObjectLifecycle; - } - } -} +namespace ento { +namespace categories { +extern const char *const CoreFoundationObjectiveC; +extern const char *const LogicError; +extern const char *const MemoryRefCount; +extern const char *const MemoryError; +extern const char *const UnixAPI; +extern const char *const CXXObjectLifecycle; +extern const char *const SecurityError; +} // namespace categories +} // namespace ento +} // namespace clang #endif - diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index fc1cc91388266..60705dd27d6b2 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -63,6 +63,9 @@ enum CallEventKind { CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember, CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor, CE_CXXConstructor, + CE_CXXInheritedConstructor, + CE_BEG_CXX_CONSTRUCTOR_CALLS = CE_CXXConstructor, + CE_END_CXX_CONSTRUCTOR_CALLS = CE_CXXInheritedConstructor, CE_CXXAllocator, CE_BEG_FUNCTION_CALLS = CE_Function, CE_END_FUNCTION_CALLS = CE_CXXAllocator, @@ -258,6 +261,13 @@ class CallEvent { /// calls. bool isCalled(const CallDescription &CD) const; + /// Returns true whether the CallEvent is any of the CallDescriptions supplied + /// as a parameter. + template + bool isCalled(const FirstCallDesc &First, const CallDescs &... Rest) const { + return isCalled(First) || isCalled(Rest...); + } + /// Returns a source range for the entire call, suitable for /// outputting in diagnostics. virtual SourceRange getSourceRange() const { @@ -811,10 +821,38 @@ class CXXDestructorCall : public CXXInstanceCall { } }; +/// Represents any constructor invocation. This includes regular constructors +/// and inherited constructors. +class AnyCXXConstructorCall : public AnyFunctionCall { +protected: + AnyCXXConstructorCall(const Expr *E, const MemRegion *Target, + ProgramStateRef St, const LocationContext *LCtx) + : AnyFunctionCall(E, St, LCtx) { + assert(E && (isa(E) || isa(E))); + // Target may be null when the region is unknown. + Data = Target; + } + + void getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const override; + + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; + +public: + /// Returns the value of the implicit 'this' object. + SVal getCXXThisVal() const; + + static bool classof(const CallEvent *Call) { + return Call->getKind() >= CE_BEG_CXX_CONSTRUCTOR_CALLS && + Call->getKind() <= CE_END_CXX_CONSTRUCTOR_CALLS; + } +}; + /// Represents a call to a C++ constructor. /// /// Example: \c T(1) -class CXXConstructorCall : public AnyFunctionCall { +class CXXConstructorCall : public AnyCXXConstructorCall { friend class CallEventManager; protected: @@ -827,17 +865,12 @@ class CXXConstructorCall : public AnyFunctionCall { /// \param LCtx The location context at this point in the program. CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) { - Data = Target; - } + : AnyCXXConstructorCall(CE, Target, St, LCtx) {} CXXConstructorCall(const CXXConstructorCall &Other) = default; void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); } - void getExtraInvalidatedValues(ValueList &Values, - RegionAndSymbolInvalidationTraits *ETraits) const override; - public: virtual const CXXConstructExpr *getOriginExpr() const { return cast(AnyFunctionCall::getOriginExpr()); @@ -853,12 +886,6 @@ class CXXConstructorCall : public AnyFunctionCall { return getOriginExpr()->getArg(Index); } - /// Returns the value of the implicit 'this' object. - SVal getCXXThisVal() const; - - void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const override; - Kind getKind() const override { return CE_CXXConstructor; } static bool classof(const CallEvent *CA) { @@ -866,6 +893,66 @@ class CXXConstructorCall : public AnyFunctionCall { } }; +/// Represents a call to a C++ inherited constructor. +/// +/// Example: \c class T : public S { using S::S; }; T(1); +class CXXInheritedConstructorCall : public AnyCXXConstructorCall { + friend class CallEventManager; + +protected: + CXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *CE, + const MemRegion *Target, ProgramStateRef St, + const LocationContext *LCtx) + : AnyCXXConstructorCall(CE, Target, St, LCtx) {} + + CXXInheritedConstructorCall(const CXXInheritedConstructorCall &Other) = + default; + + void cloneTo(void *Dest) const override { + new (Dest) CXXInheritedConstructorCall(*this); + } + +public: + virtual const CXXInheritedCtorInitExpr *getOriginExpr() const { + return cast(AnyFunctionCall::getOriginExpr()); + } + + const CXXConstructorDecl *getDecl() const override { + return getOriginExpr()->getConstructor(); + } + + /// Obtain the stack frame of the inheriting constructor. Argument expressions + /// can be found on the call site of that stack frame. + const StackFrameContext *getInheritingStackFrame() const; + + /// Obtain the CXXConstructExpr for the sub-class that inherited the current + /// constructor (possibly indirectly). It's the statement that contains + /// argument expressions. + const CXXConstructExpr *getInheritingConstructor() const { + return cast(getInheritingStackFrame()->getCallSite()); + } + + unsigned getNumArgs() const override { + return getInheritingConstructor()->getNumArgs(); + } + + const Expr *getArgExpr(unsigned Index) const override { + return getInheritingConstructor()->getArg(Index); + } + + virtual SVal getArgSVal(unsigned Index) const override { + return getState()->getSVal( + getArgExpr(Index), + getInheritingStackFrame()->getParent()->getStackFrame()); + } + + Kind getKind() const override { return CE_CXXInheritedConstructor; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXInheritedConstructor; + } +}; + /// Represents the memory allocation call in a C++ new-expression. /// /// This is a call to "operator new". @@ -1225,6 +1312,13 @@ class CallEventManager { return create(E, Target, State, LCtx); } + CallEventRef + getCXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *E, + const MemRegion *Target, ProgramStateRef State, + const LocationContext *LCtx) { + return create(E, Target, State, LCtx); + } + CallEventRef getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, const MemRegion *Target, bool IsBase, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 6e676c512b89c..c66c54116a0c6 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -527,6 +527,9 @@ class ExprEngine : public SubEngine { void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, + ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, @@ -807,10 +810,15 @@ class ExprEngine : public SubEngine { /// or unusable for any reason, a dummy temporary region is returned, and the /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts. /// Returns the updated program state and the new object's this-region. - std::pair prepareForObjectConstruction( + std::pair handleConstructionContext( const Expr *E, ProgramStateRef State, const LocationContext *LCtx, const ConstructionContext *CC, EvalCallOptions &CallOpts); + /// Common code that handles either a CXXConstructExpr or a + /// CXXInheritedCtorInitExpr. + void handleConstructor(const Expr *E, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + /// Store the location of a C++ object corresponding to a statement /// until the statement is actually encountered. For example, if a DeclStmt /// has CXXConstructExpr as its initializer, the object would be considered diff --git a/clang/include/clang/Tooling/Tooling.h b/clang/include/clang/Tooling/Tooling.h index f759789170d92..ced2405f6e837 100644 --- a/clang/include/clang/Tooling/Tooling.h +++ b/clang/include/clang/Tooling/Tooling.h @@ -225,7 +225,8 @@ std::unique_ptr buildASTFromCodeWithArgs( std::shared_ptr PCHContainerOps = std::make_shared(), ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(), - const FileContentMappings &VirtualMappedFiles = FileContentMappings()); + const FileContentMappings &VirtualMappedFiles = FileContentMappings(), + DiagnosticConsumer *DiagConsumer = nullptr); /// Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap index f36fc6bd55a4e..af1322acc289f 100644 --- a/clang/include/clang/module.modulemap +++ b/clang/include/clang/module.modulemap @@ -39,6 +39,7 @@ module Clang_Basic { textual header "Basic/Builtins.def" textual header "Basic/BuiltinsHexagon.def" textual header "Basic/BuiltinsHexagonDep.def" + textual header "Basic/BuiltinsHexagonMapCustomDep.def" textual header "Basic/BuiltinsLe64.def" textual header "Basic/BuiltinsMips.def" textual header "Basic/BuiltinsNEON.def" diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c6de2f145a071..8d8389da523ff 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -874,6 +874,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: case TargetCXXABI::WebAssembly: + case TargetCXXABI::XL: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(*this); @@ -10262,6 +10263,7 @@ MangleContext *ASTContext::createMangleContext(const TargetInfo *T) { case TargetCXXABI::iOS64: case TargetCXXABI::WebAssembly: case TargetCXXABI::WatchOS: + case TargetCXXABI::XL: return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: return MicrosoftMangleContext::create(*this, getDiagnostics()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 49058ceaab25c..066dd1b38c064 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -463,7 +463,7 @@ namespace clang { ParmVarDecl *ToParam); template - bool hasSameVisibilityContext(T *Found, T *From); + bool hasSameVisibilityContextAndLinkage(T *Found, T *From); bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -973,7 +973,10 @@ Expected ASTNodeImporter::import(const LambdaCapture &From) { } template -bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) { +bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) { + if (Found->getLinkageInternal() != From->getLinkageInternal()) + return false; + if (From->hasExternalFormalLinkage()) return Found->hasExternalFormalLinkage(); if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl()) @@ -986,8 +989,11 @@ bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) { } template <> -bool ASTNodeImporter::hasSameVisibilityContext(TypedefNameDecl *Found, +bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found, TypedefNameDecl *From) { + if (Found->getLinkageInternal() != From->getLinkageInternal()) + return false; + if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace()) return Importer.GetFromTU(Found) == From->getTranslationUnitDecl(); return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace(); @@ -2392,7 +2398,7 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundTypedef = dyn_cast(FoundDecl)) { - if (!hasSameVisibilityContext(FoundTypedef, D)) + if (!hasSameVisibilityContextAndLinkage(FoundTypedef, D)) continue; QualType FromUT = D->getUnderlyingType(); @@ -2578,6 +2584,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { IDNS |= Decl::IDNS_Ordinary; // We may already have an enum of the same name; try to find and match it. + EnumDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod() && SearchName) { SmallVector ConflictingDecls; auto FoundDecls = @@ -2592,10 +2599,15 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { } if (auto *FoundEnum = dyn_cast(FoundDecl)) { - if (!hasSameVisibilityContext(FoundEnum, D)) + if (!hasSameVisibilityContextAndLinkage(FoundEnum, D)) continue; - if (IsStructuralMatch(D, FoundEnum)) - return Importer.MapImported(D, FoundEnum); + if (IsStructuralMatch(D, FoundEnum)) { + EnumDecl *FoundDef = FoundEnum->getDefinition(); + if (D->isThisDeclarationADefinition() && FoundDef) + return Importer.MapImported(D, FoundDef); + PrevDecl = FoundEnum->getMostRecentDecl(); + break; + } ConflictingDecls.push_back(FoundDecl); } } @@ -2623,7 +2635,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { EnumDecl *D2; if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), DC, ToBeginLoc, - Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + Loc, Name.getAsIdentifierInfo(), PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed())) return D2; @@ -2709,7 +2721,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (!IsStructuralMatch(D, FoundRecord, false)) continue; - if (!hasSameVisibilityContext(FoundRecord, D)) + if (!hasSameVisibilityContextAndLinkage(FoundRecord, D)) continue; if (IsStructuralMatch(D, FoundRecord)) { @@ -3157,7 +3169,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { continue; if (auto *FoundFunction = dyn_cast(FoundDecl)) { - if (!hasSameVisibilityContext(FoundFunction, D)) + if (!hasSameVisibilityContextAndLinkage(FoundFunction, D)) continue; if (IsStructuralMatch(D, FoundFunction)) { @@ -3779,7 +3791,7 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { continue; if (auto *FoundVar = dyn_cast(FoundDecl)) { - if (!hasSameVisibilityContext(FoundVar, D)) + if (!hasSameVisibilityContextAndLinkage(FoundVar, D)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundVar->getType())) { @@ -3869,6 +3881,13 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { ToVar->setPreviousDecl(Recent); } + // Import the described template, if any. + if (D->getDescribedVarTemplate()) { + auto ToVTOrErr = import(D->getDescribedVarTemplate()); + if (!ToVTOrErr) + return ToVTOrErr.takeError(); + } + if (Error Err = ImportInitializer(D, ToVar)) return std::move(Err); @@ -5185,7 +5204,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Decl *Found = FoundDecl; auto *FoundTemplate = dyn_cast(Found); if (FoundTemplate) { - if (!hasSameVisibilityContext(FoundTemplate, D)) + if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) continue; if (IsStructuralMatch(D, FoundTemplate)) { @@ -5448,20 +5467,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( } ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { - // If this variable has a definition in the translation unit we're coming - // from, - // but this particular declaration is not that definition, import the - // definition and map to that. - auto *Definition = - cast_or_null(D->getTemplatedDecl()->getDefinition()); - if (Definition && Definition != D->getTemplatedDecl()) { - if (ExpectedDecl ImportedDefOrErr = import( - Definition->getDescribedVarTemplate())) - return Importer.MapImported(D, *ImportedDefOrErr); - else - return ImportedDefOrErr.takeError(); - } - // Import the major distinguishing characteristics of this variable template. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -5475,19 +5480,26 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // We may already have a template of the same name; try to find and match it. assert(!DC->isFunctionOrMethod() && "Variable templates cannot be declared at function scope"); + SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); + VarTemplateDecl *FoundByLookup = nullptr; for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - Decl *Found = FoundDecl; - if (VarTemplateDecl *FoundTemplate = dyn_cast(Found)) { + if (VarTemplateDecl *FoundTemplate = dyn_cast(FoundDecl)) { if (IsStructuralMatch(D, FoundTemplate)) { - // The variable templates structurally match; call it the same template. - Importer.MapImported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.MapImported(D, FoundTemplate); + // The Decl in the "From" context has a definition, but in the + // "To" context we already have a definition. + VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && FoundDef) + // FIXME Check for ODR error if the two definitions have + // different initializers? + return Importer.MapImported(D, FoundDef); + + FoundByLookup = FoundTemplate; + break; } ConflictingDecls.push_back(FoundDecl); } @@ -5532,6 +5544,18 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { ToVarTD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToVarTD); + if (FoundByLookup) { + auto *Recent = + const_cast(FoundByLookup->getMostRecentDecl()); + if (!ToTemplated->getPreviousDecl()) { + auto *PrevTemplated = + FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); + if (ToTemplated != PrevTemplated) + ToTemplated->setPreviousDecl(PrevTemplated); + } + ToVarTD->setPreviousDecl(Recent); + } + if (DTemplated->isThisDeclarationADefinition() && !ToTemplated->isThisDeclarationADefinition()) { // FIXME: Import definition! @@ -5713,7 +5737,7 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { continue; if (auto *FoundTemplate = dyn_cast(FoundDecl)) { - if (!hasSameVisibilityContext(FoundTemplate, D)) + if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) continue; if (IsStructuralMatch(D, FoundTemplate)) { FunctionTemplateDecl *TemplateWithDef = @@ -8473,6 +8497,15 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { if (!ToIncludeLoc) return ToIncludeLoc.takeError(); + // Every FileID that is not the main FileID needs to have a valid include + // location so that the include chain points to the main FileID. When + // importing the main FileID (which has no include location), we need to + // create a fake include location in the main file to keep this property + // intact. + SourceLocation ToIncludeLocOrFakeLoc = *ToIncludeLoc; + if (FromID == FromSM.getMainFileID()) + ToIncludeLocOrFakeLoc = ToSM.getLocForStartOfFile(ToSM.getMainFileID()); + if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { // FIXME: We probably want to use getVirtualFile(), so we don't hit the // disk again @@ -8484,7 +8517,7 @@ Expected ASTImporter::Import(FileID FromID, bool IsBuiltin) { // point to a valid file and we get no Entry here. In this case try with // the memory buffer below. if (Entry) - ToID = ToSM.createFileID(*Entry, *ToIncludeLoc, + ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc, FromSLoc.getFile().getFileCharacteristic()); } } diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 91a2f3a8391bb..c29b7b2f59077 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -31,10 +31,9 @@ // } // ``` // Indeed, it has it's queue, which holds pairs of nodes, one from each graph, -// this is the `DeclsToCheck` and it's pair is in `TentativeEquivalences`. -// `TentativeEquivalences` also plays the role of the marking (`marked`) -// functionality above, we use it to check whether we've already seen a pair of -// nodes. +// this is the `DeclsToCheck` member. `VisitedDecls` plays the role of the +// marking (`marked`) functionality above, we use it to check whether we've +// already seen a pair of nodes. // // We put in the elements into the queue only in the toplevel decl check // function: @@ -57,11 +56,6 @@ // doing. Thus, static implementation functions must not call the **member** // functions. // -// So, now `TentativeEquivalences` plays two roles. It is used to store the -// second half of the decls which we want to compare, plus it plays a role in -// closing the recursion. On a long term, we could refactor structural -// equivalency to be more alike to the traditional BFS. -// //===----------------------------------------------------------------------===// #include "clang/AST/ASTStructuralEquivalence.h" diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index a741ca5a80e16..da7b808e4f519 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -55,7 +55,6 @@ add_clang_library(clangAST ExternalASTSource.cpp FormatString.cpp InheritViz.cpp - Interp/Block.cpp Interp/ByteCodeEmitter.cpp Interp/ByteCodeExprGen.cpp Interp/ByteCodeGenError.cpp @@ -67,6 +66,7 @@ add_clang_library(clangAST Interp/Frame.cpp Interp/Function.cpp Interp/Interp.cpp + Interp/InterpBlock.cpp Interp/InterpFrame.cpp Interp/InterpStack.cpp Interp/InterpState.cpp diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 53c1832d1dd25..8102f0115cc78 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -12,6 +12,7 @@ #include "clang/AST/CommentDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" @@ -134,7 +135,9 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { unsigned DiagSelect; switch (Comment->getCommandID()) { case CommandTraits::KCI_class: - DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0; + DiagSelect = + (!isClassOrStructOrTagTypedefDecl() && !isClassTemplateDecl()) ? 1 + : 0; // Allow @class command on @interface declarations. // FIXME. Currently, \class and @class are indistinguishable. So, // \class is also allowed on an @interface declaration @@ -148,7 +151,7 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { DiagSelect = !isObjCProtocolDecl() ? 3 : 0; break; case CommandTraits::KCI_struct: - DiagSelect = !isClassOrStructDecl() ? 4 : 0; + DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0; break; case CommandTraits::KCI_union: DiagSelect = !isUnionDecl() ? 5 : 0; @@ -935,15 +938,50 @@ bool Sema::isUnionDecl() { return RD->isUnion(); return false; } +static bool isClassOrStructDeclImpl(const Decl *D) { + if (auto *record = dyn_cast_or_null(D)) + return !record->isUnion(); + + return false; +} bool Sema::isClassOrStructDecl() { if (!ThisDeclInfo) return false; if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return ThisDeclInfo->CurrentDecl && - isa(ThisDeclInfo->CurrentDecl) && - !isUnionDecl(); + + if (!ThisDeclInfo->CurrentDecl) + return false; + + return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl); +} + +bool Sema::isClassOrStructOrTagTypedefDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + + if (!ThisDeclInfo->CurrentDecl) + return false; + + if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl)) + return true; + + if (auto *ThisTypedefDecl = dyn_cast(ThisDeclInfo->CurrentDecl)) { + auto UnderlyingType = ThisTypedefDecl->getUnderlyingType(); + if (auto ThisElaboratedType = dyn_cast(UnderlyingType)) { + auto DesugaredType = ThisElaboratedType->desugar(); + if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) { + if (auto *ThisRecordType = dyn_cast(DesugaredTypePtr)) { + return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl()); + } + } + } + } + + return false; } bool Sema::isClassTemplateDecl() { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 931a1141b1b49..58e7e16d68172 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -663,7 +663,7 @@ bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const { // C++17 [expr.prim.lambda]p21: // The closure type associated with a lambda-expression has no default // constructor and a deleted copy assignment operator. - if (getLambdaCaptureDefault() != LCD_None || + if (getLambdaCaptureDefault() != LCD_None || getLambdaData().NumCaptures != 0) return false; return getASTContext().getLangOpts().CPlusPlus2a; @@ -2152,7 +2152,7 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, return DevirtualizedMethod; // Similarly, if the class itself or its destructor is marked 'final', - // the class can't be derived from and we can therefore devirtualize the + // the class can't be derived from and we can therefore devirtualize the // member function call. if (BestDynamicDecl->isEffectivelyFinal()) return DevirtualizedMethod; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index dfa9444c59aa9..9a31b64eedda4 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1417,6 +1417,31 @@ static bool isFormalAccess(AccessKinds AK) { return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy; } +/// Is this kind of axcess valid on an indeterminate object value? +static bool isValidIndeterminateAccess(AccessKinds AK) { + switch (AK) { + case AK_Read: + case AK_Increment: + case AK_Decrement: + // These need the object's value. + return false; + + case AK_ReadObjectRepresentation: + case AK_Assign: + case AK_Construct: + case AK_Destroy: + // Construction and destruction don't need the value. + return true; + + case AK_MemberCall: + case AK_DynamicCast: + case AK_TypeId: + // These aren't really meaningful on scalars. + return true; + } + llvm_unreachable("unknown access kind"); +} + namespace { struct ComplexValue { private: @@ -3140,6 +3165,13 @@ struct CompleteObject { : Base(Base), Value(Value), Type(Type) {} bool mayAccessMutableMembers(EvalInfo &Info, AccessKinds AK) const { + // If this isn't a "real" access (eg, if it's just accessing the type + // info), allow it. We assume the type doesn't change dynamically for + // subobjects of constexpr objects (even though we'd hit UB here if it + // did). FIXME: Is this right? + if (!isAnyAccess(AK)) + return true; + // In C++14 onwards, it is permitted to read a mutable member whose // lifetime began within the evaluation. // FIXME: Should we also allow this in C++11? @@ -3194,9 +3226,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { // Reading an indeterminate value is undefined, but assigning over one is OK. if ((O->isAbsent() && !(handler.AccessKind == AK_Construct && I == N)) || - (O->isIndeterminate() && handler.AccessKind != AK_Construct && - handler.AccessKind != AK_Assign && - handler.AccessKind != AK_ReadObjectRepresentation)) { + (O->isIndeterminate() && + !isValidIndeterminateAccess(handler.AccessKind))) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_access_uninit) << handler.AccessKind << O->isIndeterminate(); @@ -5469,6 +5500,8 @@ static bool EvaluateArgs(ArrayRef Args, ArgVector &ArgValues, } } } + // FIXME: This is the wrong evaluation order for an assignment operator + // called via operator syntax. for (unsigned Idx = 0; Idx < Args.size(); Idx++) { if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) { // If we're checking for a potential constant expression, evaluate all @@ -6929,10 +6962,8 @@ class ExprEvaluatorBase } else if (const auto *PDE = dyn_cast(Callee)) { if (!Info.getLangOpts().CPlusPlus2a) Info.CCEDiag(PDE, diag::note_constexpr_pseudo_destructor); - // FIXME: If pseudo-destructor calls ever start ending the lifetime of - // their callee, we should start calling HandleDestruction here. - // For now, we just evaluate the object argument and discard it. - return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal); + return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal) && + HandleDestruction(Info, PDE, ThisVal, PDE->getDestroyedType()); } else return Error(Callee); FD = Member; diff --git a/clang/lib/AST/Interp/Block.cpp b/clang/lib/AST/Interp/InterpBlock.cpp similarity index 98% rename from clang/lib/AST/Interp/Block.cpp rename to clang/lib/AST/Interp/InterpBlock.cpp index 5fc93eb39f4ea..ed6e8910194d8 100644 --- a/clang/lib/AST/Interp/Block.cpp +++ b/clang/lib/AST/Interp/InterpBlock.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "Block.h" +#include "InterpBlock.h" #include "Pointer.h" using namespace clang; diff --git a/clang/lib/AST/Interp/Block.h b/clang/lib/AST/Interp/InterpBlock.h similarity index 98% rename from clang/lib/AST/Interp/Block.h rename to clang/lib/AST/Interp/InterpBlock.h index 97fb9a3ca0961..0ccdef221c836 100644 --- a/clang/lib/AST/Interp/Block.h +++ b/clang/lib/AST/Interp/InterpBlock.h @@ -1,4 +1,4 @@ -//===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===// +//===-- InterpBlock.h - Allocated blocks for the interpreter -*- C++ ----*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 1a10723aaca53..ef2638e2a36bd 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "Pointer.h" -#include "Block.h" #include "Function.h" +#include "InterpBlock.h" #include "PrimType.h" using namespace clang; diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index b8fa98e24faab..f2f6e0e760185 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -13,12 +13,12 @@ #ifndef LLVM_CLANG_AST_INTERP_POINTER_H #define LLVM_CLANG_AST_INTERP_POINTER_H -#include "Block.h" #include "Descriptor.h" +#include "InterpBlock.h" +#include "clang/AST/ComparisonCategories.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" -#include "clang/AST/ComparisonCategories.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index c30b07137edcf..637b61e90a90e 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -997,7 +997,7 @@ void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break; case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break; } - + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 1aea9acc472bb..550f5aa338f1c 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -457,7 +457,7 @@ void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { } AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { - return cast(Exprs[i + NumInputs]); + return cast(Exprs[i + NumOutputs + NumInputs]); } StringRef GCCAsmStmt::getLabelName(unsigned i) const { @@ -523,7 +523,7 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { for (unsigned i = 0, e = getNumLabels(); i != e; ++i) if (getLabelName(i) == SymbolicName) - return i + getNumInputs(); + return i + getNumOutputs() + getNumInputs(); // Not found. return -1; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 14ddc13ce561d..76c5fe2e54029 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1387,7 +1387,7 @@ void StmtProfiler::VisitRequiresExpr(const RequiresExpr *S) { ID.AddInteger(concepts::Requirement::RK_Nested); auto *NestedReq = cast(Req); ID.AddBoolean(NestedReq->isSubstitutionFailure()); - if (!NestedReq->isSubstitutionFailure()) + if (!NestedReq->isSubstitutionFailure()) Visit(NestedReq->getConstraintExpr()); } } diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index fe121727c749c..59c77a167b1f3 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -42,11 +42,7 @@ namespace ast_matchers { AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector, Matches) { - std::string SelString = Node.getSelector().getAsString(); - for (const std::string &S : Matches) - if (S == SelString) - return true; - return false; + return llvm::is_contained(Matches, Node.getSelector().getAsString()); } namespace internal { @@ -312,11 +308,9 @@ bool AllOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, // allOf leads to one matcher for each alternative in the first // matcher combined with each alternative in the second matcher. // Thus, we can reuse the same Builder. - for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { - if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder)) - return false; - } - return true; + return llvm::all_of(InnerMatchers, [&](const DynTypedMatcher &InnerMatcher) { + return InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder); + }); } bool EachOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, @@ -365,14 +359,15 @@ bool OptionallyVariadicOperator(const DynTypedNode &DynNode, inline static std::vector vectorFromRefs(ArrayRef NameRefs) { std::vector Names; + Names.reserve(NameRefs.size()); for (auto *Name : NameRefs) Names.emplace_back(*Name); return Names; } Matcher hasAnyNameFunc(ArrayRef NameRefs) { - std::vector Names = vectorFromRefs(NameRefs); - return internal::Matcher(new internal::HasNameMatcher(Names)); + return internal::Matcher( + new internal::HasNameMatcher(vectorFromRefs(NameRefs))); } Matcher hasAnySelectorFunc( @@ -380,10 +375,13 @@ Matcher hasAnySelectorFunc( return hasAnySelectorMatcher(vectorFromRefs(NameRefs)); } +HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef NameRefs) { + return HasOpNameMatcher(vectorFromRefs(NameRefs)); +} + HasNameMatcher::HasNameMatcher(std::vector N) - : UseUnqualifiedMatch(std::all_of( - N.begin(), N.end(), - [](StringRef Name) { return Name.find("::") == Name.npos; })), + : UseUnqualifiedMatch(llvm::all_of( + N, [](StringRef Name) { return Name.find("::") == Name.npos; })), Names(std::move(N)) { #ifndef NDEBUG for (StringRef Name : Names) @@ -441,6 +439,7 @@ namespace { class PatternSet { public: PatternSet(ArrayRef Names) { + Patterns.reserve(Names.size()); for (StringRef Name : Names) Patterns.push_back({Name, Name.startswith("::")}); } @@ -465,10 +464,10 @@ class PatternSet { /// A match will be a pattern that was fully consumed, that also matches the /// 'fully qualified' requirement. bool foundMatch(bool AllowFullyQualified) const { - for (auto& P: Patterns) - if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified)) - return true; - return false; + return llvm::any_of(Patterns, [&](const Pattern &Pattern) { + return Pattern.P.empty() && + (AllowFullyQualified || !Pattern.IsFullyQualified); + }); } private: @@ -854,6 +853,10 @@ const internal::VariadicOperatorMatcherFunc< const internal::VariadicFunction, StringRef, internal::hasAnyNameFunc> hasAnyName = {}; + +const internal::VariadicFunction + hasAnyOperatorName = {}; const internal::VariadicFunction, StringRef, internal::hasAnySelectorFunc> hasAnySelector = {}; diff --git a/clang/lib/ASTMatchers/CMakeLists.txt b/clang/lib/ASTMatchers/CMakeLists.txt index cd88d1db9ce43..8f700ca3226be 100644 --- a/clang/lib/ASTMatchers/CMakeLists.txt +++ b/clang/lib/ASTMatchers/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangASTMatchers ASTMatchFinder.cpp ASTMatchersInternal.cpp + GtestMatchers.cpp LINK_LIBS clangAST diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 7344c622cc9d7..5452b408a817f 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -243,6 +243,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasAnyConstructorInitializer); REGISTER_MATCHER(hasAnyDeclaration); REGISTER_MATCHER(hasAnyName); + REGISTER_MATCHER(hasAnyOperatorName); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnyPlacementArg); REGISTER_MATCHER(hasAnySelector); diff --git a/clang/lib/ASTMatchers/GtestMatchers.cpp b/clang/lib/ASTMatchers/GtestMatchers.cpp new file mode 100644 index 0000000000000..c99fdf6c0fcd6 --- /dev/null +++ b/clang/lib/ASTMatchers/GtestMatchers.cpp @@ -0,0 +1,104 @@ +//===- GtestMatchers.cpp - AST Matchers for Gtest ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/ASTMatchers/GtestMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Timer.h" +#include +#include +#include + +namespace clang { +namespace ast_matchers { + +static DeclarationMatcher getComparisonDecl(GtestCmp Cmp) { + switch (Cmp) { + case GtestCmp::Eq: + return cxxMethodDecl(hasName("Compare"), + ofClass(cxxRecordDecl(isSameOrDerivedFrom( + hasName("::testing::internal::EqHelper"))))); + case GtestCmp::Ne: + return functionDecl(hasName("::testing::internal::CmpHelperNE")); + case GtestCmp::Ge: + return functionDecl(hasName("::testing::internal::CmpHelperGE")); + case GtestCmp::Gt: + return functionDecl(hasName("::testing::internal::CmpHelperGT")); + case GtestCmp::Le: + return functionDecl(hasName("::testing::internal::CmpHelperLE")); + case GtestCmp::Lt: + return functionDecl(hasName("::testing::internal::CmpHelperLT")); + } + llvm_unreachable("Unhandled GtestCmp enum"); +} + +static llvm::StringRef getAssertMacro(GtestCmp Cmp) { + switch (Cmp) { + case GtestCmp::Eq: + return "ASSERT_EQ"; + case GtestCmp::Ne: + return "ASSERT_NE"; + case GtestCmp::Ge: + return "ASSERT_GE"; + case GtestCmp::Gt: + return "ASSERT_GT"; + case GtestCmp::Le: + return "ASSERT_LE"; + case GtestCmp::Lt: + return "ASSERT_LT"; + } + llvm_unreachable("Unhandled GtestCmp enum"); +} + +static llvm::StringRef getExpectMacro(GtestCmp Cmp) { + switch (Cmp) { + case GtestCmp::Eq: + return "EXPECT_EQ"; + case GtestCmp::Ne: + return "EXPECT_NE"; + case GtestCmp::Ge: + return "EXPECT_GE"; + case GtestCmp::Gt: + return "EXPECT_GT"; + case GtestCmp::Le: + return "EXPECT_LE"; + case GtestCmp::Lt: + return "EXPECT_LT"; + } + llvm_unreachable("Unhandled GtestCmp enum"); +} + +// In general, AST matchers cannot match calls to macros. However, we can +// simulate such matches if the macro definition has identifiable elements that +// themselves can be matched. In that case, we can match on those elements and +// then check that the match occurs within an expansion of the desired +// macro. The more uncommon the identified elements, the more efficient this +// process will be. +// +// We use this approach to implement the derived matchers gtestAssert and +// gtestExpect. +internal::BindableMatcher gtestAssert(GtestCmp Cmp, StatementMatcher Left, + StatementMatcher Right) { + return callExpr(callee(getComparisonDecl(Cmp)), + isExpandedFromMacro(getAssertMacro(Cmp)), + hasArgument(2, Left), hasArgument(3, Right)); +} + +internal::BindableMatcher gtestExpect(GtestCmp Cmp, StatementMatcher Left, + StatementMatcher Right) { + return callExpr(callee(getComparisonDecl(Cmp)), + isExpandedFromMacro(getExpectMacro(Cmp)), + hasArgument(2, Left), hasArgument(3, Right)); +} + +} // end namespace ast_matchers +} // end namespace clang diff --git a/clang/lib/Analysis/RetainSummaryManager.cpp b/clang/lib/Analysis/RetainSummaryManager.cpp index 181ff1b11502e..00bc854a88049 100644 --- a/clang/lib/Analysis/RetainSummaryManager.cpp +++ b/clang/lib/Analysis/RetainSummaryManager.cpp @@ -663,6 +663,7 @@ RetainSummaryManager::getSummary(AnyCall C, switch (C.getKind()) { case AnyCall::Function: case AnyCall::Constructor: + case AnyCall::InheritedConstructor: case AnyCall::Allocator: case AnyCall::Deallocator: Summ = getFunctionSummary(cast_or_null(C.getDecl())); diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index ff14e18ec144e..a4a900c8146a5 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -475,6 +475,7 @@ class TransferFunctions : public StmtVisitor { void VisitCallExpr(CallExpr *ce); void VisitDeclRefExpr(DeclRefExpr *dr); void VisitDeclStmt(DeclStmt *ds); + void VisitGCCAsmStmt(GCCAsmStmt *as); void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); void VisitObjCMessageExpr(ObjCMessageExpr *ME); void VisitOMPExecutableDirective(OMPExecutableDirective *ED); @@ -760,6 +761,16 @@ void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { } } +void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) { + // An "asm goto" statement is a terminator that may initialize some variables. + if (!as->isAsmGoto()) + return; + + for (const auto &o : as->outputs()) + if (const VarDecl *VD = findVar(o).getDecl()) + vals[VD] = Initialized; +} + void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) { // If the Objective-C message expression is an implicit no-return that // is not modeled in the CFG, set the tracked dataflow values to Unknown. @@ -797,6 +808,10 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg, if (Optional cs = I.getAs()) tf.Visit(const_cast(cs->getStmt())); } + CFGTerminator terminator = block->getTerminator(); + if (GCCAsmStmt *as = dyn_cast_or_null(terminator.getStmt())) + if (as->isAsmGoto()) + tf.Visit(as); return vals.updateValueVectorWithScratch(block); } diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index e4d019aedb7c2..ac8af8fcaf4ae 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -513,7 +513,7 @@ FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status, StatCache.get(), *FS); } -std::error_code +std::error_code FileManager::getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result) { SmallString<128> FilePath(Path); diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index cba3e3ada7ea5..bd1a8834c2fa3 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -194,6 +194,13 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__LP64__"); } + std::string CodeModel = getTargetOpts().CodeModel; + if (CodeModel == "default") + CodeModel = "small"; + for (char &c : CodeModel) + c = toupper(c); + Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__"); + // ACLE predefines. Many can only have one possible value on v8 AArch64. Builder.defineMacro("__ARM_ACLE", "200"); Builder.defineMacro("__ARM_ARCH", "8"); diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index 456cb2ebb8b55..ed6929214f6e0 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -263,6 +263,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { Opts.support("cl_khr_int64_base_atomics"); Opts.support("cl_khr_int64_extended_atomics"); Opts.support("cl_khr_mipmap_image"); + Opts.support("cl_khr_mipmap_image_writes"); Opts.support("cl_khr_subgroups"); Opts.support("cl_khr_3d_image_writes"); Opts.support("cl_amd_media_ops"); diff --git a/clang/lib/Basic/Targets/Hexagon.cpp b/clang/lib/Basic/Targets/Hexagon.cpp index fcf9e9cff31da..205601c359d04 100644 --- a/clang/lib/Basic/Targets/Hexagon.cpp +++ b/clang/lib/Basic/Targets/Hexagon.cpp @@ -24,6 +24,8 @@ void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__qdsp6__", "1"); Builder.defineMacro("__hexagon__", "1"); + Builder.defineMacro("__ELF__"); + // The macro __HVXDBL__ is deprecated. bool DefineHvxDbl = false; diff --git a/clang/lib/Basic/Targets/Hexagon.h b/clang/lib/Basic/Targets/Hexagon.h index 2a72825e3c5a3..f58f594b104fe 100644 --- a/clang/lib/Basic/Targets/Hexagon.h +++ b/clang/lib/Basic/Targets/Hexagon.h @@ -57,6 +57,12 @@ class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo { LargeArrayAlign = 64; UseBitFieldTypeAlignment = true; ZeroLengthBitfieldBoundary = 32; + + // These are the default values anyway, but explicitly make sure + // that the size of the boolean type is 8 bits. Bool vectors are used + // for modeling predicate registers in HVX, and the bool -> byte + // correspondence matches the HVX architecture. + BoolWidth = BoolAlign = 8; } ArrayRef getTargetBuiltins() const override; diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 70fac030bc5d8..e57ad7b9eeaf6 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -706,6 +706,8 @@ class AIXTargetInfo : public OSTargetInfo { public: AIXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : OSTargetInfo(Triple, Opts) { + this->TheCXXABI.set(TargetCXXABI::XL); + if (this->PointerWidth == 64) { this->WCharType = this->UnsignedInt; } else { diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index d099d3742f0b2..7b575f52bb22d 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -911,7 +911,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, std::string CodeModel = getTargetOpts().CodeModel; if (CodeModel == "default") CodeModel = "small"; - Builder.defineMacro("__code_model_" + CodeModel + "_"); + Builder.defineMacro("__code_model_" + CodeModel + "__"); // Target identification. if (getTriple().getArch() == llvm::Triple::x86_64) { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 959451b667a98..0401aa26dcbc6 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -51,6 +51,10 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Coroutines.h" +#include "llvm/Transforms/Coroutines/CoroCleanup.h" +#include "llvm/Transforms/Coroutines/CoroEarly.h" +#include "llvm/Transforms/Coroutines/CoroElide.h" +#include "llvm/Transforms/Coroutines/CoroSplit.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" @@ -358,7 +362,7 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, break; case CodeGenOptions::MASSV: TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::MASSV); - break; + break; case CodeGenOptions::SVML: TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML); break; @@ -967,6 +971,22 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { } } +static void addCoroutinePassesAtO0(ModulePassManager &MPM, + const LangOptions &LangOpts, + const CodeGenOptions &CodeGenOpts) { + if (!LangOpts.Coroutines) + return; + + MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); + + CGSCCPassManager CGPM(CodeGenOpts.DebugPassManager); + CGPM.addPass(CoroSplitPass()); + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CoroElidePass())); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + + MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); +} + static void addSanitizersAtO0(ModulePassManager &MPM, const Triple &TargetTriple, const LangOptions &LangOpts, @@ -1086,6 +1106,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( PTO.LoopInterleaving = CodeGenOpts.UnrollLoops; PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; + PTO.Coroutines = LangOpts.Coroutines; PassInstrumentationCallbacks PIC; StandardInstrumentations SI; @@ -1289,6 +1310,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( } if (CodeGenOpts.OptimizationLevel == 0) { + addCoroutinePassesAtO0(MPM, LangOpts, CodeGenOpts); addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts); } } diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 7687f7990d996..38e96c0f4ee67 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -22,16 +22,15 @@ class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. -class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter { +class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} -protected: /// This forwards to CodeGenFunction::InsertHelper. void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB, - llvm::BasicBlock::iterator InsertPt) const; + llvm::BasicBlock::iterator InsertPt) const override; private: CodeGenFunction *CGF = nullptr; }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 6e28ff41482b0..77e95e0bd6688 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1629,7 +1629,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ceilf: case Builtin::BI__builtin_ceilf16: case Builtin::BI__builtin_ceill: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::ceil, Intrinsic::experimental_constrained_ceil)); @@ -1650,7 +1650,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_cosf: case Builtin::BI__builtin_cosf16: case Builtin::BI__builtin_cosl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::cos, Intrinsic::experimental_constrained_cos)); @@ -1661,7 +1661,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_expf: case Builtin::BI__builtin_expf16: case Builtin::BI__builtin_expl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::exp, Intrinsic::experimental_constrained_exp)); @@ -1672,7 +1672,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_exp2f: case Builtin::BI__builtin_exp2f16: case Builtin::BI__builtin_exp2l: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::exp2, Intrinsic::experimental_constrained_exp2)); @@ -1693,7 +1693,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_floorf: case Builtin::BI__builtin_floorf16: case Builtin::BI__builtin_floorl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::floor, Intrinsic::experimental_constrained_floor)); @@ -1704,7 +1704,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fmaf: case Builtin::BI__builtin_fmaf16: case Builtin::BI__builtin_fmal: - return RValue::get(emitTernaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitTernaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::fma, Intrinsic::experimental_constrained_fma)); @@ -1715,7 +1715,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fmaxf: case Builtin::BI__builtin_fmaxf16: case Builtin::BI__builtin_fmaxl: - return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::maxnum, Intrinsic::experimental_constrained_maxnum)); @@ -1726,7 +1726,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminf16: case Builtin::BI__builtin_fminl: - return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::minnum, Intrinsic::experimental_constrained_minnum)); @@ -1751,7 +1751,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_logf: case Builtin::BI__builtin_logf16: case Builtin::BI__builtin_logl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::log, Intrinsic::experimental_constrained_log)); @@ -1762,7 +1762,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_log10f: case Builtin::BI__builtin_log10f16: case Builtin::BI__builtin_log10l: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::log10, Intrinsic::experimental_constrained_log10)); @@ -1773,7 +1773,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_log2f: case Builtin::BI__builtin_log2f16: case Builtin::BI__builtin_log2l: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::log2, Intrinsic::experimental_constrained_log2)); @@ -1783,7 +1783,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_nearbyint: case Builtin::BI__builtin_nearbyintf: case Builtin::BI__builtin_nearbyintl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::nearbyint, Intrinsic::experimental_constrained_nearbyint)); @@ -1794,7 +1794,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_powf: case Builtin::BI__builtin_powf16: case Builtin::BI__builtin_powl: - return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::pow, Intrinsic::experimental_constrained_pow)); @@ -1805,7 +1805,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_rintf: case Builtin::BI__builtin_rintf16: case Builtin::BI__builtin_rintl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::rint, Intrinsic::experimental_constrained_rint)); @@ -1816,7 +1816,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_roundf: case Builtin::BI__builtin_roundf16: case Builtin::BI__builtin_roundl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::round, Intrinsic::experimental_constrained_round)); @@ -1827,7 +1827,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_sinf: case Builtin::BI__builtin_sinf16: case Builtin::BI__builtin_sinl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::sin, Intrinsic::experimental_constrained_sin)); @@ -1838,7 +1838,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_sqrtf: case Builtin::BI__builtin_sqrtf16: case Builtin::BI__builtin_sqrtl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::sqrt, Intrinsic::experimental_constrained_sqrt)); @@ -1849,7 +1849,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_truncf: case Builtin::BI__builtin_truncf16: case Builtin::BI__builtin_truncl: - return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(*this, E, Intrinsic::trunc, Intrinsic::experimental_constrained_trunc)); @@ -3962,19 +3962,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Create a vector of the arguments, as well as a constant value to // express to the runtime the number of variadic arguments. - std::vector Args = { - Queue, Flags, Range, - Kernel, Block, ConstantInt::get(IntTy, NumArgs - 4), - ElemPtr}; - std::vector ArgTys = { + llvm::Value *const Args[] = {Queue, Flags, + Range, Kernel, + Block, ConstantInt::get(IntTy, NumArgs - 4), + ElemPtr}; + llvm::Type *const ArgTys[] = { QueueTy, IntTy, RangeTy, GenericVoidPtrTy, GenericVoidPtrTy, IntTy, ElemPtr->getType()}; - llvm::FunctionType *FTy = llvm::FunctionType::get( - Int32Ty, llvm::ArrayRef(ArgTys), false); - auto Call = - RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), - llvm::ArrayRef(Args))); + llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false); + auto Call = RValue::get( + Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), Args)); if (TmpSize) EmitLifetimeEnd(TmpSize, TmpPtr); return Call; @@ -7064,6 +7062,58 @@ static llvm::Value *ARMMVEVectorReinterpret(CGBuilderTy &Builder, } } +static llvm::Value *VectorUnzip(CGBuilderTy &Builder, llvm::Value *V, bool Odd) { + // Make a shufflevector that extracts every other element of a vector (evens + // or odds, as desired). + SmallVector Indices; + unsigned InputElements = V->getType()->getVectorNumElements(); + for (unsigned i = 0; i < InputElements; i += 2) + Indices.push_back(i + Odd); + return Builder.CreateShuffleVector(V, llvm::UndefValue::get(V->getType()), + Indices); +} + +static llvm::Value *VectorZip(CGBuilderTy &Builder, llvm::Value *V0, + llvm::Value *V1) { + // Make a shufflevector that interleaves two vectors element by element. + assert(V0->getType() == V1->getType() && "Can't zip different vector types"); + SmallVector Indices; + unsigned InputElements = V0->getType()->getVectorNumElements(); + for (unsigned i = 0; i < InputElements; i++) { + Indices.push_back(i); + Indices.push_back(i + InputElements); + } + return Builder.CreateShuffleVector(V0, V1, Indices); +} + +template +static llvm::Value *ARMMVEConstantSplat(CGBuilderTy &Builder, llvm::Type *VT) { + // MVE-specific helper function to make a vector splat of a constant such as + // UINT_MAX or INT_MIN, in which all bits below the highest one are equal. + llvm::Type *T = VT->getVectorElementType(); + unsigned LaneBits = T->getPrimitiveSizeInBits(); + uint32_t Value = HighBit << (LaneBits - 1); + if (OtherBits) + Value |= (1UL << (LaneBits - 1)) - 1; + llvm::Value *Lane = llvm::ConstantInt::get(T, Value); + return ARMMVEVectorSplat(Builder, Lane); +} + +static llvm::Value *ARMMVEVectorElementReverse(CGBuilderTy &Builder, + llvm::Value *V, + unsigned ReverseWidth) { + // MVE-specific helper function which reverses the elements of a + // vector within every (ReverseWidth)-bit collection of lanes. + SmallVector Indices; + unsigned LaneSize = V->getType()->getScalarSizeInBits(); + unsigned Elements = 128 / LaneSize; + unsigned Mask = ReverseWidth / LaneSize - 1; + for (unsigned i = 0; i < Elements; i++) + Indices.push_back(i ^ Mask); + return Builder.CreateShuffleVector(V, llvm::UndefValue::get(V->getType()), + Indices); +} + Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue, @@ -10108,7 +10158,8 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef Ops, // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding). if (IID != Intrinsic::not_intrinsic && - cast(Ops.back())->getZExtValue() != (uint64_t)4) { + (cast(Ops.back())->getZExtValue() != (uint64_t)4 || + IsAddSub)) { Function *Intr = CGF.CGM.getIntrinsic(IID); Res = CGF.Builder.CreateCall(Intr, {A, B, C, Ops.back() }); } else { @@ -10121,24 +10172,6 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef Ops, FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty); Res = CGF.Builder.CreateCall(FMA, {A, B, C}); } - - if (IsAddSub) { - // Negate even elts in C using a mask. - unsigned NumElts = Ty->getVectorNumElements(); - SmallVector Indices(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Indices[i] = i + (i % 2) * NumElts; - - // FIXME: This code isn't exception safe for constrained FP. We need to - // suppress exceptions on the unselected elements. - Value *NegC = CGF.Builder.CreateFNeg(C); - Value *FMSub; - if (CGF.Builder.getIsFPConstrained()) - FMSub = CGF.Builder.CreateConstrainedFPCall(FMA, {A, B, NegC} ); - else - FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} ); - Res = CGF.Builder.CreateShuffleVector(FMSub, Res, Indices); - } } // Handle any required masking. @@ -10774,10 +10807,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_vfmaddpd512_mask3: case X86::BI__builtin_ia32_vfmsubpd512_mask3: return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/false); - case X86::BI__builtin_ia32_vfmaddsubps: - case X86::BI__builtin_ia32_vfmaddsubpd: - case X86::BI__builtin_ia32_vfmaddsubps256: - case X86::BI__builtin_ia32_vfmaddsubpd256: case X86::BI__builtin_ia32_vfmaddsubps512_mask: case X86::BI__builtin_ia32_vfmaddsubps512_maskz: case X86::BI__builtin_ia32_vfmaddsubps512_mask3: @@ -13269,6 +13298,21 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_cosf: case AMDGPU::BI__builtin_amdgcn_cosh: return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_cos); + case AMDGPU::BI__builtin_amdgcn_dispatch_ptr: { + auto *F = CGM.getIntrinsic(Intrinsic::amdgcn_dispatch_ptr); + auto *Call = Builder.CreateCall(F); + Call->addAttribute( + AttributeList::ReturnIndex, + Attribute::getWithDereferenceableBytes(Call->getContext(), 64)); + Call->addAttribute( + AttributeList::ReturnIndex, + Attribute::getWithAlignment(Call->getContext(), Align(4))); + QualType BuiltinRetType = E->getType(); + auto *RetTy = cast(ConvertType(BuiltinRetType)); + if (RetTy == Call->getType()) + return Call; + return Builder.CreateAddrSpaceCast(Call, RetTy); + } case AMDGPU::BI__builtin_amdgcn_log_clampf: return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_log_clamp); case AMDGPU::BI__builtin_amdgcn_ldexp: @@ -13311,7 +13355,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Value *Src2 = EmitScalarExpr(E->getArg(2)); // FIXME-GFX10: How should 32 bit mask be handled? - Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_icmp, + Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_icmp, { Builder.getInt64Ty(), Src0->getType() }); return Builder.CreateCall(F, { Src0, Src1, Src2 }); } @@ -13322,7 +13366,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Value *Src2 = EmitScalarExpr(E->getArg(2)); // FIXME-GFX10: How should 32 bit mask be handled? - Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_fcmp, + Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_fcmp, { Builder.getInt64Ty(), Src0->getType() }); return Builder.CreateCall(F, { Src0, Src1, Src2 }); } @@ -14963,10 +15007,46 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } } +static std::pair +getIntrinsicForHexagonNonGCCBuiltin(unsigned BuiltinID) { + struct Info { + unsigned BuiltinID; + Intrinsic::ID IntrinsicID; + unsigned VecLen; + }; + Info Infos[] = { +#define CUSTOM_BUILTIN_MAPPING(x,s) \ + { Hexagon::BI__builtin_HEXAGON_##x, Intrinsic::hexagon_##x, s }, + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstoreq, 64) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorenq, 64) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentq, 64) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentnq, 64) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstoreq_128B, 128) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorenq_128B, 128) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentq_128B, 128) + CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentnq_128B, 128) +#include "clang/Basic/BuiltinsHexagonMapCustomDep.def" +#undef CUSTOM_BUILTIN_MAPPING + }; + + auto CmpInfo = [] (Info A, Info B) { return A.BuiltinID < B.BuiltinID; }; + static const bool SortOnce = (llvm::sort(Infos, CmpInfo), true); + (void)SortOnce; + + const Info *F = std::lower_bound(std::begin(Infos), std::end(Infos), + Info{BuiltinID, 0, 0}, CmpInfo); + if (F == std::end(Infos) || F->BuiltinID != BuiltinID) + return {Intrinsic::not_intrinsic, 0}; + + return {F->IntrinsicID, F->VecLen}; +} + Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { SmallVector Ops; - Intrinsic::ID ID = Intrinsic::not_intrinsic; + Intrinsic::ID ID; + unsigned VecLen; + std::tie(ID, VecLen) = getIntrinsicForHexagonNonGCCBuiltin(BuiltinID); auto MakeCircLd = [&](unsigned IntID, bool HasImm) { // The base pointer is passed by address, so it needs to be loaded. @@ -15055,51 +15135,41 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, return Builder.CreateExtractValue(Result, 1); }; + auto V2Q = [this, VecLen] (llvm::Value *Vec) { + Intrinsic::ID ID = VecLen == 128 ? Intrinsic::hexagon_V6_vandvrt_128B + : Intrinsic::hexagon_V6_vandvrt; + return Builder.CreateCall(CGM.getIntrinsic(ID), + {Vec, Builder.getInt32(-1)}); + }; + auto Q2V = [this, VecLen] (llvm::Value *Pred) { + Intrinsic::ID ID = VecLen == 128 ? Intrinsic::hexagon_V6_vandqrt_128B + : Intrinsic::hexagon_V6_vandqrt; + return Builder.CreateCall(CGM.getIntrinsic(ID), + {Pred, Builder.getInt32(-1)}); + }; + switch (BuiltinID) { + // These intrinsics return a tuple {Vector, VectorPred} in LLVM IR, + // and the corresponding C/C++ builtins use loads/stores to update + // the predicate. case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry: - case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: { - Address Dest = EmitPointerWithAlignment(E->getArg(2)); - unsigned Size; - if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vaddcarry) { - Size = 512; - ID = Intrinsic::hexagon_V6_vaddcarry; - } else { - Size = 1024; - ID = Intrinsic::hexagon_V6_vaddcarry_128B; - } - Dest = Builder.CreateBitCast(Dest, - llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0)); - LoadInst *QLd = Builder.CreateLoad(Dest); - Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd }; - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1); - llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)), - Vprd->getType()->getPointerTo(0)); - Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment()); - return Builder.CreateExtractValue(Result, 0); - } + case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry: case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B: { - Address Dest = EmitPointerWithAlignment(E->getArg(2)); - unsigned Size; - if (BuiltinID == Hexagon::BI__builtin_HEXAGON_V6_vsubcarry) { - Size = 512; - ID = Intrinsic::hexagon_V6_vsubcarry; - } else { - Size = 1024; - ID = Intrinsic::hexagon_V6_vsubcarry_128B; - } - Dest = Builder.CreateBitCast(Dest, - llvm::VectorType::get(Builder.getInt1Ty(), Size)->getPointerTo(0)); - LoadInst *QLd = Builder.CreateLoad(Dest); - Ops = { EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), QLd }; - llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - llvm::Value *Vprd = Builder.CreateExtractValue(Result, 1); - llvm::Value *Base = Builder.CreateBitCast(EmitScalarExpr(E->getArg(2)), - Vprd->getType()->getPointerTo(0)); - Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment()); + // Get the type from the 0-th argument. + llvm::Type *VecType = ConvertType(E->getArg(0)->getType()); + Address PredAddr = Builder.CreateBitCast( + EmitPointerWithAlignment(E->getArg(2)), VecType->getPointerTo(0)); + llvm::Value *PredIn = V2Q(Builder.CreateLoad(PredAddr)); + llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID), + {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); + + llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } + case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci: return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pci, /*HasImm*/true); case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci: @@ -15156,8 +15226,38 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, return MakeBrevLd(Intrinsic::hexagon_L2_loadri_pbr, Int32Ty); case Hexagon::BI__builtin_brev_ldd: return MakeBrevLd(Intrinsic::hexagon_L2_loadrd_pbr, Int64Ty); - default: - break; + default: { + if (ID == Intrinsic::not_intrinsic) + return nullptr; + + auto IsVectorPredTy = [] (llvm::Type *T) { + return T->isVectorTy() && T->getVectorElementType()->isIntegerTy(1); + }; + + llvm::Function *IntrFn = CGM.getIntrinsic(ID); + llvm::FunctionType *IntrTy = IntrFn->getFunctionType(); + SmallVector Ops; + for (unsigned i = 0, e = IntrTy->getNumParams(); i != e; ++i) { + llvm::Type *T = IntrTy->getParamType(i); + const Expr *A = E->getArg(i); + if (IsVectorPredTy(T)) { + // There will be an implicit cast to a boolean vector. Strip it. + if (auto *Cast = dyn_cast(A)) { + if (Cast->getCastKind() == CK_BitCast) + A = Cast->getSubExpr(); + } + Ops.push_back(V2Q(EmitScalarExpr(A))); + } else { + Ops.push_back(EmitScalarExpr(A)); + } + } + + llvm::Value *Call = Builder.CreateCall(IntrFn, Ops); + if (IsVectorPredTy(IntrTy->getReturnType())) + Call = Q2V(Call); + + return Call; + } // default } // switch return nullptr; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3151f4ecbffb5..f28e3cd2aba9d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3901,6 +3901,10 @@ template class AbstractAssumeAlignedAttrEmitter { const auto *AlignmentCI = dyn_cast(Alignment); if (!AlignmentCI) return Attrs; + // We may legitimately have non-power-of-2 alignment here. + // If so, this is UB land, emit it via `@llvm.assume` instead. + if (!AlignmentCI->getValue().isPowerOf2()) + return Attrs; llvm::AttributeList NewAttrs = maybeRaiseRetAlignmentAttribute( CGF.getLLVMContext(), Attrs, llvm::Align( diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5c1e09b8e9a06..5fee639b22c29 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1548,9 +1548,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // is rare. if (!Bypasses.IsBypassed(&D) && !(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) { - uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy); + llvm::TypeSize size = + CGM.getDataLayout().getTypeAllocSize(allocaTy); emission.SizeForLifetimeMarkers = - EmitLifetimeStart(size, AllocaAddr.getPointer()); + size.isScalable() ? EmitLifetimeStart(-1, AllocaAddr.getPointer()) + : EmitLifetimeStart(size.getFixedSize(), + AllocaAddr.getPointer()); } } else { assert(!emission.useLifetimeMarkers()); diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 61801e0e815ba..db78309e9fd9f 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -821,7 +821,7 @@ class CGObjCGNUstep : public CGObjCGNU { // Slot_t objc_slot_lookup_super(struct objc_super*, SEL); SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, PtrToObjCSuperTy, SelectorTy); - // If we're in ObjC++ mode, then we want to make + // If we're in ObjC++ mode, then we want to make if (usesSEHExceptions) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void objc_exception_rethrow(void) @@ -1657,7 +1657,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { b.CreateRetVoid(); // We can't use the normal LLVM global initialisation array, because we // need to specify that this runs early in library initialisation. - auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), + auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), /*isConstant*/true, llvm::GlobalValue::InternalLinkage, Init, ".objc_early_init_ptr"); InitVar->setSection(".CRT$XCLb"); diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index f8b831d0e9bed..c34758c7e3b3f 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -211,7 +211,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc); } - + // Emit the try body. CGF.EmitStmt(S.getTryBody()); @@ -271,7 +271,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, cleanups.ForceCleanup(); CGF.EmitBranchThroughCleanup(Cont); - } + } // Go back to the try-statement fallthrough. CGF.Builder.restoreIP(SavedIP); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 9798d454cb8b6..f00dcfe731fda 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11075,9 +11075,7 @@ static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, SmallVector VariantExprs; SmallVector VMIs; for (const auto *A : FD->specific_attrs()) { - A->printPretty(llvm::dbgs(), PrintingPolicy(LangOptions())); const OMPTraitInfo &TI = A->getTraitInfos(); - TI.print(llvm::dbgs(), PrintingPolicy(LangOptions())); VMIs.push_back(VariantMatchInfo()); TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back()); VariantExprs.push_back(A->getVariantFuncRef()); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index a39d2b225b2e9..3bdf8fc59b0b9 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2234,13 +2234,6 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Constraints += InputConstraint; } - // Append the "input" part of inout constraints last. - for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { - ArgTypes.push_back(InOutArgTypes[i]); - Args.push_back(InOutArgs[i]); - } - Constraints += InOutConstraints; - // Labels SmallVector Transfer; llvm::BasicBlock *Fallthrough = nullptr; @@ -2248,7 +2241,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { if (const auto *GS = dyn_cast(&S)) { IsGCCAsmGoto = GS->isAsmGoto(); if (IsGCCAsmGoto) { - for (auto *E : GS->labels()) { + for (const auto *E : GS->labels()) { JumpDest Dest = getJumpDestForLabel(E->getLabel()); Transfer.push_back(Dest.getBlock()); llvm::BlockAddress *BA = @@ -2259,11 +2252,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Constraints += ','; Constraints += 'X'; } - StringRef Name = "asm.fallthrough"; - Fallthrough = createBasicBlock(Name); + Fallthrough = createBasicBlock("asm.fallthrough"); } } + // Append the "input" part of inout constraints last. + for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { + ArgTypes.push_back(InOutArgTypes[i]); + Args.push_back(InOutArgs[i]); + } + Constraints += InOutConstraints; + // Clobbers for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { StringRef Clobber = S.getClobber(i); @@ -2316,9 +2315,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { if (IsGCCAsmGoto) { llvm::CallBrInst *Result = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); + EmitBlock(Fallthrough); UpdateAsmCallInst(cast(*Result), HasSideEffect, ReadOnly, ReadNone, S, ResultRegTypes, *this, RegResults); - EmitBlock(Fallthrough); } else { llvm::CallInst *Result = Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index d7115e00836c8..bcd2d0635caf1 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1450,15 +1450,7 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { // The cleanup callback that finalizes all variabels at the given location, // thus calls destructors etc. auto FiniCB = [this](InsertPointTy IP) { - CGBuilderTy::InsertPointGuard IPG(Builder); - assert(IP.getBlock()->end() != IP.getPoint() && - "OpenMP IR Builder should cause terminated block!"); - llvm::BasicBlock *IPBB = IP.getBlock(); - llvm::BasicBlock *DestBB = IPBB->splitBasicBlock(IP.getPoint()); - IPBB->getTerminator()->eraseFromParent(); - Builder.SetInsertPoint(IPBB); - CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB); - EmitBranchThroughCleanup(Dest); + OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); }; // Privatization callback that performs appropriate action for @@ -1480,25 +1472,10 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { auto BodyGenCB = [ParallelRegionBodyStmt, this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, llvm::BasicBlock &ContinuationBB) { - auto OldAllocaIP = AllocaInsertPt; - AllocaInsertPt = &*AllocaIP.getPoint(); - - auto OldReturnBlock = ReturnBlock; - ReturnBlock = getJumpDestInCurrentScope(&ContinuationBB); - - llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); - CodeGenIPBB->splitBasicBlock(CodeGenIP.getPoint()); - llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator(); - CodeGenIPBBTI->removeFromParent(); - - Builder.SetInsertPoint(CodeGenIPBB); - - EmitStmt(ParallelRegionBodyStmt); - - Builder.Insert(CodeGenIPBBTI); - - AllocaInsertPt = OldAllocaIP; - ReturnBlock = OldReturnBlock; + OMPBuilderCBHelpers::OutlinedRegionBodyRAII ORB(*this, AllocaIP, + ContinuationBB); + OMPBuilderCBHelpers::EmitOMPRegionBody(*this, ParallelRegionBodyStmt, + CodeGenIP, ContinuationBB); }; CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); @@ -3152,55 +3129,18 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { const CapturedStmt *CS = S.getInnermostCapturedStmt(); const Stmt *MasterRegionBodyStmt = CS->getCapturedStmt(); - // TODO: Replace with a generic helper function for finalization auto FiniCB = [this](InsertPointTy IP) { - CGBuilderTy::InsertPointGuard IPG(Builder); - assert(IP.getBlock()->end() != IP.getPoint() && - "OpenMP IR Builder should cause terminated block!"); - - llvm::BasicBlock *IPBB = IP.getBlock(); - llvm::BasicBlock *DestBB = IPBB->getUniqueSuccessor(); - assert(DestBB && "Finalization block should have one successor!"); - - // erase and replace with cleanup branch. - IPBB->getTerminator()->eraseFromParent(); - Builder.SetInsertPoint(IPBB); - CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB); - EmitBranchThroughCleanup(Dest); + OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); }; - // TODO: Replace with a generic helper function for emitting body auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB) { - // Alloca insertion block should be in the entry block of the containing - // function So it expects an empty AllocaIP in which case will reuse the - // old alloca insertion point, or a new AllocaIP in the same block as the - // old one - assert((!AllocaIP.isSet() || - AllocaInsertPt->getParent() == AllocaIP.getBlock()) && - "Insertion point should be in the entry block of containing " - "function!"); - auto OldAllocaIP = AllocaInsertPt; - if (AllocaIP.isSet()) - AllocaInsertPt = &*AllocaIP.getPoint(); - auto OldReturnBlock = ReturnBlock; - ReturnBlock = getJumpDestInCurrentScope(&FiniBB); - - llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); - if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator()) - CodeGenIPBBTI->eraseFromParent(); - - Builder.SetInsertPoint(CodeGenIPBB); - - EmitStmt(MasterRegionBodyStmt); - - if (Builder.saveIP().isSet()) - Builder.CreateBr(&FiniBB); - - AllocaInsertPt = OldAllocaIP; - ReturnBlock = OldReturnBlock; + OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB); + OMPBuilderCBHelpers::EmitOMPRegionBody(*this, MasterRegionBodyStmt, + CodeGenIP, FiniBB); }; + CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI); Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB)); @@ -3229,53 +3169,16 @@ void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { HintInst = Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false); - // TODO: Replace with a generic helper function for finalization auto FiniCB = [this](InsertPointTy IP) { - CGBuilderTy::InsertPointGuard IPG(Builder); - assert(IP.getBlock()->end() != IP.getPoint() && - "OpenMP IR Builder should cause terminated block!"); - llvm::BasicBlock *IPBB = IP.getBlock(); - llvm::BasicBlock *DestBB = IPBB->getUniqueSuccessor(); - assert(DestBB && "Finalization block should have one successor!"); - - // erase and replace with cleanup branch. - IPBB->getTerminator()->eraseFromParent(); - Builder.SetInsertPoint(IPBB); - CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB); - EmitBranchThroughCleanup(Dest); + OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); }; - // TODO: Replace with a generic helper function for emitting body auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB) { - // Alloca insertion block should be in the entry block of the containing - // function So it expects an empty AllocaIP in which case will reuse the - // old alloca insertion point, or a new AllocaIP in the same block as the - // old one - assert((!AllocaIP.isSet() || - AllocaInsertPt->getParent() == AllocaIP.getBlock()) && - "Insertion point should be in the entry block of containing " - "function!"); - auto OldAllocaIP = AllocaInsertPt; - if (AllocaIP.isSet()) - AllocaInsertPt = &*AllocaIP.getPoint(); - auto OldReturnBlock = ReturnBlock; - ReturnBlock = getJumpDestInCurrentScope(&FiniBB); - - llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); - if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator()) - CodeGenIPBBTI->eraseFromParent(); - - Builder.SetInsertPoint(CodeGenIPBB); - - EmitStmt(CriticalRegionBodyStmt); - - if (Builder.saveIP().isSet()) - Builder.CreateBr(&FiniBB); - - AllocaInsertPt = OldAllocaIP; - ReturnBlock = OldReturnBlock; + OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB); + OMPBuilderCBHelpers::EmitOMPRegionBody(*this, CriticalRegionBodyStmt, + CodeGenIP, FiniBB); }; CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 09c2b6f70331c..de9a9385f2f9a 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -1159,6 +1159,9 @@ void CodeGenAction::ExecuteAction() { CI.getTargetOpts(), CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, std::move(LinkModules), *VMContext, nullptr); + // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be + // true here because the valued names are needed for reading textual IR. + Ctx.setDiscardValueNames(false); Ctx.setDiagnosticHandler( std::make_unique(CodeGenOpts, &Result)); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index bffe8e7b4e954..196274a962882 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -36,6 +36,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/SanitizerStats.h" @@ -255,6 +256,114 @@ class CodeGenFunction : public CodeGenTypeCache { unsigned Index; }; + // Helper class for the OpenMP IR Builder. Allows reusability of code used for + // region body, and finalization codegen callbacks. This will class will also + // contain privatization functions used by the privatization call backs + struct OMPBuilderCBHelpers { + + using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; + + /// Emit the Finalization for an OMP region + /// \param CGF The Codegen function this belongs to + /// \param IP Insertion point for generating the finalization code. + static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP) { + CGBuilderTy::InsertPointGuard IPG(CGF.Builder); + assert(IP.getBlock()->end() != IP.getPoint() && + "OpenMP IR Builder should cause terminated block!"); + + llvm::BasicBlock *IPBB = IP.getBlock(); + llvm::BasicBlock *DestBB = IPBB->getUniqueSuccessor(); + assert(DestBB && "Finalization block should have one successor!"); + + // erase and replace with cleanup branch. + IPBB->getTerminator()->eraseFromParent(); + CGF.Builder.SetInsertPoint(IPBB); + CodeGenFunction::JumpDest Dest = CGF.getJumpDestInCurrentScope(DestBB); + CGF.EmitBranchThroughCleanup(Dest); + } + + /// Emit the body of an OMP region + /// \param CGF The Codegen function this belongs to + /// \param RegionBodyStmt The body statement for the OpenMP region being + /// generated + /// \param CodeGenIP Insertion point for generating the body code. + /// \param FiniBB The finalization basic block + static void EmitOMPRegionBody(CodeGenFunction &CGF, + const Stmt *RegionBodyStmt, + InsertPointTy CodeGenIP, + llvm::BasicBlock &FiniBB) { + llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); + if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator()) + CodeGenIPBBTI->eraseFromParent(); + + CGF.Builder.SetInsertPoint(CodeGenIPBB); + + CGF.EmitStmt(RegionBodyStmt); + + if (CGF.Builder.saveIP().isSet()) + CGF.Builder.CreateBr(&FiniBB); + } + + /// RAII for preserving necessary info during Outlined region body codegen. + class OutlinedRegionBodyRAII { + + llvm::AssertingVH OldAllocaIP; + CodeGenFunction::JumpDest OldReturnBlock; + CodeGenFunction &CGF; + + public: + OutlinedRegionBodyRAII(CodeGenFunction &cgf, InsertPointTy &AllocaIP, + llvm::BasicBlock &RetBB) + : CGF(cgf) { + assert(AllocaIP.isSet() && + "Must specify Insertion point for allocas of outlined function"); + OldAllocaIP = CGF.AllocaInsertPt; + CGF.AllocaInsertPt = &*AllocaIP.getPoint(); + + OldReturnBlock = CGF.ReturnBlock; + CGF.ReturnBlock = CGF.getJumpDestInCurrentScope(&RetBB); + } + + ~OutlinedRegionBodyRAII() { + CGF.AllocaInsertPt = OldAllocaIP; + CGF.ReturnBlock = OldReturnBlock; + } + }; + + /// RAII for preserving necessary info during inlined region body codegen. + class InlinedRegionBodyRAII { + + llvm::AssertingVH OldAllocaIP; + CodeGenFunction &CGF; + + public: + InlinedRegionBodyRAII(CodeGenFunction &cgf, InsertPointTy &AllocaIP, + llvm::BasicBlock &FiniBB) + : CGF(cgf) { + // Alloca insertion block should be in the entry block of the containing + // function so it expects an empty AllocaIP in which case will reuse the + // old alloca insertion point, or a new AllocaIP in the same block as + // the old one + assert((!AllocaIP.isSet() || + CGF.AllocaInsertPt->getParent() == AllocaIP.getBlock()) && + "Insertion point should be in the entry block of containing " + "function!"); + OldAllocaIP = CGF.AllocaInsertPt; + if (AllocaIP.isSet()) + CGF.AllocaInsertPt = &*AllocaIP.getPoint(); + + // TODO: Remove the call, after making sure the counter is not used by + // the EHStack. + // Since this is an inlined region, it should not modify the + // ReturnBlock, and should reuse the one for the enclosing outlined + // region. So, the JumpDest being return by the function is discarded + (void)CGF.getJumpDestInCurrentScope(&FiniBB); + } + + ~InlinedRegionBodyRAII() { CGF.AllocaInsertPt = OldAllocaIP; } + }; + }; + CodeGenModule &CGM; // Per-module state. const TargetInfo &Target; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 151b42e7b3347..3aaa8ec0a5665 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -84,6 +84,7 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) { case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: case TargetCXXABI::WebAssembly: + case TargetCXXABI::XL: return CreateItaniumCXXABI(CGM); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(CGM); @@ -3478,6 +3479,32 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { return true; } +static void maybeEmitPipeStorageMetadata(const VarDecl *D, + llvm::GlobalVariable *GV, + CodeGenModule &CGM) { + // TODO: Applicable only on pipe storages. Currently they are defined + // as structures inside of SYCL headers. Add a check for pipe_storage_t + // when it ready. + QualType PipeTy = D->getType(); + if (!PipeTy->isStructureType()) + return; + + if (auto *IOAttr = D->getAttr()) { + llvm::APSInt ID(32); + llvm::LLVMContext &Context = CGM.getLLVMContext(); + bool IsValid = + IOAttr->getID()->isIntegerConstantExpr(ID, D->getASTContext()); + assert(IsValid && "Not an integer constant expression"); + (void)IsValid; + + llvm::Metadata *AttrMDArgs[] = { + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(Context), ID.getSExtValue()))}; + GV->setMetadata(IOAttr->getSpelling(), + llvm::MDNode::get(Context, AttrMDArgs)); + } +} + /// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module, /// create and return an llvm GlobalVariable with the specified type. If there /// is something in the module with the specified name, return it potentially @@ -3667,6 +3694,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, : (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default); assert(getContext().getTargetAddressSpace(ExpectedAS) == Ty->getPointerAddressSpace()); + + if (LangOpts.SYCLIsDevice) + maybeEmitPipeStorageMetadata(D, GV, *this); + if (AddrSpace != ExpectedAS) return getTargetCodeGenInfo().performAddrSpaceCast(*this, GV, AddrSpace, ExpectedAS, Ty); @@ -4318,6 +4349,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (CGDebugInfo *DI = getModuleDebugInfo()) if (getCodeGenOpts().hasReducedDebugInfo()) DI->EmitGlobalVariable(GV, D); + + if (LangOpts.SYCLIsDevice) + maybeEmitPipeStorageMetadata(D, GV, *this); } void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) { diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 3be4da7b86702..aa32d83de0af0 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -525,23 +525,44 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case BuiltinType::OCLReserveID: ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty); break; - - // TODO: real CodeGen support for SVE types requires more infrastructure - // to be added first. Report an error until then. -#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: -#include "clang/Basic/AArch64SVEACLETypes.def" - { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "cannot yet generate code for SVE type '%0'"); - auto *BT = cast(Ty); - auto Name = BT->getName(CGM.getContext().getPrintingPolicy()); - CGM.getDiags().Report(DiagID) << Name; - // Return something safe. - ResultType = llvm::IntegerType::get(getLLVMContext(), 32); + case BuiltinType::SveInt8: + case BuiltinType::SveUint8: + return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), + {16, true}); + case BuiltinType::SveInt16: + case BuiltinType::SveUint16: + return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), + {8, true}); + case BuiltinType::SveInt32: + case BuiltinType::SveUint32: + return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 32), + {4, true}); + case BuiltinType::SveInt64: + case BuiltinType::SveUint64: + return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 64), + {2, true}); + case BuiltinType::SveFloat16: + return llvm::VectorType::get( + getTypeForFormat(getLLVMContext(), + Context.getFloatTypeSemantics(Context.HalfTy), + /* UseNativeHalf = */ true), + {8, true}); + case BuiltinType::SveFloat32: + return llvm::VectorType::get( + getTypeForFormat(getLLVMContext(), + Context.getFloatTypeSemantics(Context.FloatTy), + /* UseNativeHalf = */ false), + {4, true}); + case BuiltinType::SveFloat64: + return llvm::VectorType::get( + getTypeForFormat(getLLVMContext(), + Context.getFloatTypeSemantics(Context.DoubleTy), + /* UseNativeHalf = */ false), + {2, true}); + case BuiltinType::SveBool: + return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 1), + {16, true}); break; - } - case BuiltinType::Dependent: #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 057c726e355e3..c8a73c2757ab2 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -516,6 +516,16 @@ class WebAssemblyCXXABI final : public ItaniumCXXABI { } bool canCallMismatchedFunctionType() const override { return false; } }; + +class XLCXXABI final : public ItaniumCXXABI { +public: + explicit XLCXXABI(CodeGen::CodeGenModule &CGM) + : ItaniumCXXABI(CGM) {} + + void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, + llvm::FunctionCallee dtor, + llvm::Constant *addr) override; +}; } CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { @@ -546,6 +556,9 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { case TargetCXXABI::WebAssembly: return new WebAssemblyCXXABI(CGM); + case TargetCXXABI::XL: + return new XLCXXABI(CGM); + case TargetCXXABI::GenericItanium: if (CGM.getContext().getTargetInfo().getTriple().getArch() == llvm::Triple::le32) { @@ -4407,3 +4420,11 @@ void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF, NormalCleanup, cast(CGF.CurrentFuncletPad)); ItaniumCXXABI::emitBeginCatch(CGF, C); } + +/// Register a global destructor as best as we know how. +void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, + llvm::FunctionCallee dtor, + llvm::Constant *addr) { + llvm::report_fatal_error("Static initialization has not been implemented on" + " XL ABI yet."); +} diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 886d9c7c1b787..f24ea2daf14ef 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1687,7 +1687,7 @@ void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State) c isHomogeneousAggregate(Ty, Base, NumElts)) { if (State.FreeSSERegs >= NumElts) { State.FreeSSERegs -= NumElts; - Args[I].info = ABIArgInfo::getDirect(); + Args[I].info = ABIArgInfo::getDirectInReg(); State.IsPreassigned.set(I); } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f35dd6c76be25..611a2e1b9dd47 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -534,7 +534,7 @@ static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { static bool useFramePointerForTargetByDefault(const ArgList &Args, const llvm::Triple &Triple) { - if (Args.hasArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_pg) && !Args.hasArg(options::OPT_mfentry)) return true; switch (Triple.getArch()) { @@ -2020,21 +2020,19 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args, options::OPT_mno_backchain, false); bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack, options::OPT_mno_packed_stack, false); - if (HasBackchain && HasPackedStack) { + systemz::FloatABI FloatABI = + systemz::getSystemZFloatABI(getToolChain().getDriver(), Args); + bool HasSoftFloat = (FloatABI == systemz::FloatABI::Soft); + if (HasBackchain && HasPackedStack && !HasSoftFloat) { const Driver &D = getToolChain().getDriver(); D.Diag(diag::err_drv_unsupported_opt) - << Args.getLastArg(options::OPT_mpacked_stack)->getAsString(Args) + - " " + Args.getLastArg(options::OPT_mbackchain)->getAsString(Args); + << "-mpacked-stack -mbackchain -mhard-float"; } if (HasBackchain) CmdArgs.push_back("-mbackchain"); if (HasPackedStack) CmdArgs.push_back("-mpacked-stack"); - - systemz::FloatABI FloatABI = - systemz::getSystemZFloatABI(getToolChain().getDriver(), Args); - - if (FloatABI == systemz::FloatABI::Soft) { + if (HasSoftFloat) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); CmdArgs.push_back("-mfloat-abi"); @@ -4417,8 +4415,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Discard value names in assert builds unless otherwise specified. if (Args.hasFlag(options::OPT_fdiscard_value_names, - options::OPT_fno_discard_value_names, !IsAssertBuild)) + options::OPT_fno_discard_value_names, !IsAssertBuild)) { + if (Args.hasArg(options::OPT_fdiscard_value_names) && + (std::any_of(Inputs.begin(), Inputs.end(), + [](const clang::driver::InputInfo &II) { + return types::isLLVMIR(II.getType()); + }))) { + D.Diag(diag::warn_ignoring_fdiscard_for_bitcode); + } CmdArgs.push_back("-discard-value-names"); + } // Set the main file name, so that debug info works even with // -save-temps. @@ -4755,8 +4761,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (void)Args.hasArg(options::OPT_mtune_EQ); if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { - CmdArgs.push_back("-mcode-model"); - CmdArgs.push_back(A->getValue()); + StringRef CM = A->getValue(); + if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" || + CM == "tiny") + A->render(Args, CmdArgs); + else + D.Diag(diag::err_drv_invalid_argument_to_option) + << CM << A->getOption().getName(); } if (Arg *A = Args.getLastArg(options::OPT_mtls_size_EQ)) { @@ -4838,11 +4849,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_v); - Args.AddLastArg(CmdArgs, options::OPT_H); + + if (Args.getLastArg(options::OPT_H)) { + CmdArgs.push_back("-H"); + CmdArgs.push_back("-sys-header-deps"); + } + if (D.CCPrintHeaders && !D.CCGenDiagnostics) { CmdArgs.push_back("-header-include-file"); CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename : "-"); + CmdArgs.push_back("-sys-header-deps"); } Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); @@ -5968,7 +5985,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Arg->render(Args, OriginalArgs); SmallString<256> Flags; - Flags += Exec; + EscapeSpacesAndBackslashes(Exec, Flags); for (const char *OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); @@ -6300,7 +6317,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (FPKeepKind == CodeGenOptions::FramePointerKind::None) + if (FPKeepKind == CodeGenOptions::FramePointerKind::None && + !Args.hasArg(options::OPT_mfentry)) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); @@ -6577,7 +6595,13 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("--dependent-lib=oldnames"); } - Args.AddLastArg(CmdArgs, options::OPT_show_includes); + if (Arg *ShowIncludes = + Args.getLastArg(options::OPT__SLASH_showIncludes, + options::OPT__SLASH_showIncludes_user)) { + CmdArgs.push_back("--show-includes"); + if (ShowIncludes->getOption().matches(options::OPT__SLASH_showIncludes)) + CmdArgs.push_back("-sys-header-deps"); + } // This controls whether or not we emit RTTI data for polymorphic types. if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, @@ -6937,7 +6961,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); - Flags += Exec; + EscapeSpacesAndBackslashes(Exec, Flags); for (const char *OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 97f7905685c12..c9f87e0e43556 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1144,8 +1144,10 @@ void Darwin::addProfileRTLibs(const ArgList &Args, if (hasExportSymbolDirective(Args)) { if (ForGCOV) { addExportedSymbol(CmdArgs, "___gcov_flush"); + addExportedSymbol(CmdArgs, "___gcov_fork"); addExportedSymbol(CmdArgs, "_flush_fn_list"); addExportedSymbol(CmdArgs, "_writeout_fn_list"); + addExportedSymbol(CmdArgs, "_reset_fn_list"); } else { addExportedSymbol(CmdArgs, "___llvm_profile_filename"); addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); @@ -1899,7 +1901,7 @@ void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs CIncludeDirs.split(dirs, ":"); for (llvm::StringRef dir : dirs) { llvm::StringRef Prefix = - llvm::sys::path::is_absolute(dir) ? llvm::StringRef(Sysroot) : ""; + llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } } else { diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 6114829ac8e18..fbda60ac7a459 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -289,7 +289,7 @@ void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs, CIncludeDirs.split(dirs, ":"); for (StringRef dir : dirs) { StringRef Prefix = - llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; + llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } return; diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index f5ff6795c1f6b..af44268a02856 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1588,7 +1588,7 @@ static void findRISCVBareMetalMultilibs(const Driver &D, }; // currently only support the set of multilibs like riscv-gnu-toolchain does. // TODO: support MULTILIB_REUSE - SmallVector RISCVMultilibSet = { + constexpr RiscvMultilib RISCVMultilibSet[] = { {"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"}, {"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"}, {"rv64imafdc", "lp64d"}}; diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp index 2b9046712a261..25e9f1b6c2228 100644 --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -540,6 +540,13 @@ void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, return; const Driver &D = getDriver(); + if (!D.SysRoot.empty()) { + SmallString<128> P(D.SysRoot); + llvm::sys::path::append(P, "include"); + addExternCSystemInclude(DriverArgs, CC1Args, P.str()); + return; + } + std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), D.PrefixDirs); addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include"); diff --git a/clang/lib/Driver/ToolChains/Hurd.cpp b/clang/lib/Driver/ToolChains/Hurd.cpp index 51d9c28244ab6..72286bd09f135 100644 --- a/clang/lib/Driver/ToolChains/Hurd.cpp +++ b/clang/lib/Driver/ToolChains/Hurd.cpp @@ -149,7 +149,7 @@ void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs, CIncludeDirs.split(Dirs, ":"); for (StringRef Dir : Dirs) { StringRef Prefix = - llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : ""; + llvm::sys::path::is_absolute(Dir) ? "" : StringRef(SysRoot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir); } return; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index cc3fa40007aa8..18f46e9402ea7 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -681,7 +681,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, CIncludeDirs.split(dirs, ":"); for (StringRef dir : dirs) { StringRef Prefix = - llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : ""; + llvm::sys::path::is_absolute(dir) ? "" : StringRef(SysRoot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } return; diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp index fc4e2cf151ef1..0a1ac0b225868 100644 --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -244,7 +244,7 @@ void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs, CIncludeDirs.split(dirs, ":"); for (StringRef dir : dirs) { StringRef Prefix = - llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; + llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } return; diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index adf8eb077201c..461ec75d17f69 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -283,7 +283,7 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs, CIncludeDirs.split(dirs, ":"); for (StringRef dir : dirs) { StringRef Prefix = - llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; + llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot); addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } return; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index e9cd327754efe..dc68cbc797341 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -103,6 +103,7 @@ namespace format { TYPE(UnaryOperator) \ TYPE(CSharpStringLiteral) \ TYPE(CSharpNullCoalescing) \ + TYPE(CSharpNamedArgument) \ TYPE(Unknown) enum TokenType { diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index e76d74571ebc3..8acae56e22327 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -76,6 +76,8 @@ void FormatTokenLexer::tryMergePreviousTokens() { return; if (Style.isCSharp()) { + if (tryMergeCSharpNamedArgument()) + return; if (tryMergeCSharpAttributeAndTarget()) return; if (tryMergeCSharpKeywordVariables()) @@ -184,6 +186,39 @@ bool FormatTokenLexer::tryMergeJSPrivateIdentifier() { return true; } +// Merge 'argName' and ':' into a single token in `foo(argName: bar)`. +bool FormatTokenLexer::tryMergeCSharpNamedArgument() { + if (Tokens.size() < 2) + return false; + auto &Colon = *(Tokens.end() - 1); + if (!Colon->is(tok::colon)) + return false; + + auto &Name = *(Tokens.end() - 2); + if (!Name->is(tok::identifier)) + return false; + + const FormatToken *CommaOrLeftParen = nullptr; + for (auto I = Tokens.rbegin() + 2, E = Tokens.rend(); I != E; ++I) { + // NB: Because previous pointers are not initialized yet, this cannot use + // Token.getPreviousNonComment. + if ((*I)->isNot(tok::comment)) { + CommaOrLeftParen = *I; + break; + } + } + + if (!CommaOrLeftParen || !CommaOrLeftParen->isOneOf(tok::l_paren, tok::comma)) + return false; + + Name->TokenText = StringRef(Name->TokenText.begin(), + Colon->TokenText.end() - Name->TokenText.begin()); + Name->ColumnWidth += Colon->ColumnWidth; + Name->Type = TT_CSharpNamedArgument; + Tokens.erase(Tokens.end() - 1); + return true; +} + // Search for verbatim or interpolated string literals @"ABC" or // $"aaaaa{abc}aaaaa" i and mark the token as TT_CSharpStringLiteral, and to // prevent splitting of @, $ and ". diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 4fffb36272f76..1f930d75e805a 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -56,6 +56,7 @@ class FormatTokenLexer { bool tryMergeCSharpDoubleQuestion(); bool tryTransformCSharpForEach(); bool tryMergeCSharpAttributeAndTarget(); + bool tryMergeCSharpNamedArgument(); bool tryMergeTokens(ArrayRef Kinds, TokenType NewType); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 42963ca105a95..d71c4f4703780 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -819,10 +819,15 @@ class AnnotatingParser { Tok->Type = TT_BitFieldColon; } else if (Contexts.size() == 1 && !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) { - if (Tok->getPreviousNonComment()->isOneOf(tok::r_paren, - tok::kw_noexcept)) + FormatToken *Prev = Tok->getPreviousNonComment(); + if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept)) Tok->Type = TT_CtorInitializerColon; - else + else if (Prev->is(tok::kw_try)) { + // Member initializer list within function try block. + FormatToken *PrevPrev = Prev->getPreviousNonComment(); + if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept)) + Tok->Type = TT_CtorInitializerColon; + } else Tok->Type = TT_InheritanceColon; } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next && (Tok->Next->isOneOf(tok::r_paren, tok::comma) || diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 0e1b5e95e9ddd..da9ee41da71b6 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -292,6 +292,13 @@ class LineJoiner { } } + // Try to merge a CSharp property declaration like `{ get; private set }`. + if (Style.isCSharp()) { + unsigned CSPA = tryMergeCSharpPropertyAccessor(I, E, Limit); + if (CSPA > 0) + return CSPA; + } + // Try to merge a function block with left brace unwrapped if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last) { @@ -421,6 +428,64 @@ class LineJoiner { return 0; } + // true for lines of the form [access-modifier] {get,set} [;] + bool isMergeablePropertyAccessor(const AnnotatedLine *Line) { + auto *Tok = Line->First; + if (!Tok) + return false; + + if (Tok->isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private, + Keywords.kw_internal)) + Tok = Tok->Next; + + if (!Tok || (Tok->TokenText != "get" && Tok->TokenText != "set")) + return false; + + if (!Tok->Next || Tok->Next->is(tok::semi)) + return true; + + return false; + } + + unsigned tryMergeCSharpPropertyAccessor( + SmallVectorImpl::const_iterator I, + SmallVectorImpl::const_iterator E, unsigned /*Limit*/) { + + auto CurrentLine = I; + // Does line start with `{` + if (!(*CurrentLine)->Last || (*CurrentLine)->Last->isNot(TT_FunctionLBrace)) + return 0; + ++CurrentLine; + + unsigned MergedLines = 0; + bool HasGetOrSet = false; + while (CurrentLine != E) { + bool LineIsGetOrSet = isMergeablePropertyAccessor(*CurrentLine); + HasGetOrSet = HasGetOrSet || LineIsGetOrSet; + if (LineIsGetOrSet) { + ++CurrentLine; + ++MergedLines; + continue; + } + auto *Tok = (*CurrentLine)->First; + if (Tok && Tok->is(tok::r_brace)) { + ++CurrentLine; + ++MergedLines; + // See if the next line is a default value so that we can merge `{ get; + // set } = 0` + if (CurrentLine != E && (*CurrentLine)->First && + (*CurrentLine)->First->is(tok::equal)) { + ++MergedLines; + } + break; + } + // Not a '}' or a get/set line so do not merege lines. + return 0; + } + + return HasGetOrSet ? MergedLines : 0; + } + unsigned tryMergeSimplePPDirective(SmallVectorImpl::const_iterator I, SmallVectorImpl::const_iterator E, diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index b455a7f2ebedb..802bb514a38f7 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1849,11 +1849,20 @@ void UnwrappedLineParser::parseTryCatch() { if (FormatTok->is(tok::colon)) { // We are in a function try block, what comes is an initializer list. nextToken(); + + // In case identifiers were removed by clang-tidy, what might follow is + // multiple commas in sequence - before the first identifier. + while (FormatTok->is(tok::comma)) + nextToken(); + while (FormatTok->is(tok::identifier)) { nextToken(); if (FormatTok->is(tok::l_paren)) parseParens(); - if (FormatTok->is(tok::comma)) + + // In case identifiers were removed by clang-tidy, what might follow is + // multiple commas in sequence - after the first identifier. + while (FormatTok->is(tok::comma)) nextToken(); } } diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index dec281529b9e4..1486adf70c3fb 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -189,7 +189,7 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( Clang->getASTConsumer().GetASTDeserializationListener()); if (!Reader) return nullptr; - Clang->setModuleManager(Reader); + Clang->setASTReader(Reader); Clang->getASTContext().setExternalSource(Reader); } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index fe787918b41bc..bf246f48f7ff6 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -138,7 +138,7 @@ std::unique_ptr CompilerInstance::takeSema() { IntrusiveRefCntPtr CompilerInstance::getASTReader() const { return TheASTReader; } -void CompilerInstance::setModuleManager(IntrusiveRefCntPtr Reader) { +void CompilerInstance::setASTReader(IntrusiveRefCntPtr Reader) { assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() && "Expected ASTReader to use the same PCM cache"); TheASTReader = std::move(Reader); @@ -379,7 +379,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { const PreprocessorOptions &PPOpts = getPreprocessorOpts(); - // The module manager holds a reference to the old preprocessor (if any). + // The AST reader holds a reference to the old preprocessor (if any). TheASTReader.reset(); // Create the Preprocessor. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d6962f132f42a..7f558410a2a7e 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -528,17 +528,6 @@ static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) { Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments); } -static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) { - if (Arg *A = Args.getLastArg(OPT_mcode_model)) { - StringRef Value = A->getValue(); - if (Value == "small" || Value == "kernel" || Value == "medium" || - Value == "large" || Value == "tiny") - return Value; - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value; - } - return "default"; -} - static llvm::Reloc::Model getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) { if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) { @@ -3525,7 +3514,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { - Opts.CodeModel = std::string(getCodeModel(Args, Diags)); + Opts.CodeModel = std::string(Args.getLastArgValue(OPT_mcmodel_EQ, "default")); Opts.ABI = std::string(Args.getLastArgValue(OPT_target_abi)); if (Arg *A = Args.getLastArg(OPT_meabi)) { StringRef Value = A->getValue(); diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index d2b6288aaa85f..549919ea8c7a4 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -137,9 +137,10 @@ struct DepCollectorASTListener : public ASTReaderListener { }; } // end anonymous namespace -void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule, - bool IsSystem, bool IsModuleFile, - bool IsMissing) { +void DependencyCollector::maybeAddDependency(StringRef Filename, + bool FromModule, bool IsSystem, + bool IsModuleFile, + bool IsMissing) { if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) addDependency(Filename); } @@ -160,8 +161,8 @@ static bool isSpecialFilename(StringRef Filename) { } bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule, - bool IsSystem, bool IsModuleFile, - bool IsMissing) { + bool IsSystem, bool IsModuleFile, + bool IsMissing) { return !isSpecialFilename(Filename) && (needSystemDependencies() || !IsSystem); } diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 99f022786e6b3..1dc85d967ca01 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -840,7 +840,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, source = createChainedIncludesSource(CI, FinalReader); if (!source) goto failure; - CI.setModuleManager(static_cast(FinalReader.get())); + CI.setASTReader(static_cast(FinalReader.get())); CI.getASTContext().setExternalSource(source); } else if (CI.getLangOpts().Modules || !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { @@ -870,7 +870,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!CI.getASTContext().getExternalSource()) goto failure; } - // If modules are enabled, create the module manager before creating + // If modules are enabled, create the AST reader before creating // any builtins, so that all declarations know that they might be // extended by an external source. if (CI.getLangOpts().Modules || !CI.hasASTContext() || diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 5f91157816b03..97fac8a26faea 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -127,8 +127,8 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, void HeaderIncludesCallback::FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind NewFileType, - FileID PrevFID) { + SrcMgr::CharacteristicKind NewFileType, + FileID PrevFID) { // Unless we are exiting a #include, make sure to skip ahead to the line the // #include directive was at. PresumedLoc UserLoc = SM.getPresumedLoc(Loc); @@ -167,6 +167,9 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc, else if (!DepOpts.ShowIncludesPretendHeader.empty()) ++IncludeDepth; // Pretend inclusion by ShowIncludesPretendHeader. + if (!DepOpts.IncludeSystemHeaders && isSystem(NewFileType)) + ShowHeader = false; + // Dump the header include information we are past the predefines buffer or // are showing all headers and this isn't the magic implicit // header. diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index eb105e63da26a..43cc9462fc2c7 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -344,13 +344,27 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, MacroBuilder &Builder) { + // C++ [cpp.predefined]p1: + // The following macro names shall be defined by the implementation: + + // -- __STDC__ + // [C++] Whether __STDC__ is predefined and if so, what its value is, + // are implementation-defined. + // (Removed in C++20.) if (!LangOpts.MSVCCompat && !LangOpts.TraditionalCPP) Builder.defineMacro("__STDC__"); + // -- __STDC_HOSTED__ + // The integer literal 1 if the implementation is a hosted + // implementation or the integer literal 0 if it is not. if (LangOpts.Freestanding) Builder.defineMacro("__STDC_HOSTED__", "0"); else Builder.defineMacro("__STDC_HOSTED__"); + // -- __STDC_VERSION__ + // [C++] Whether __STDC_VERSION__ is predefined and if so, what its + // value is, are implementation-defined. + // (Removed in C++20.) if (!LangOpts.CPlusPlus) { if (LangOpts.C17) Builder.defineMacro("__STDC_VERSION__", "201710L"); @@ -361,33 +375,29 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, else if (!LangOpts.GNUMode && LangOpts.Digraphs) Builder.defineMacro("__STDC_VERSION__", "199409L"); } else { - // FIXME: Use correct value for C++20. + // -- __cplusplus + // [C++20] The integer literal 202002L. if (LangOpts.CPlusPlus2a) - Builder.defineMacro("__cplusplus", "201707L"); - // C++17 [cpp.predefined]p1: - // The name __cplusplus is defined to the value 201703L when compiling a - // C++ translation unit. + Builder.defineMacro("__cplusplus", "202002L"); + // [C++17] The integer literal 201703L. else if (LangOpts.CPlusPlus17) Builder.defineMacro("__cplusplus", "201703L"); - // C++1y [cpp.predefined]p1: - // The name __cplusplus is defined to the value 201402L when compiling a - // C++ translation unit. + // [C++14] The name __cplusplus is defined to the value 201402L when + // compiling a C++ translation unit. else if (LangOpts.CPlusPlus14) Builder.defineMacro("__cplusplus", "201402L"); - // C++11 [cpp.predefined]p1: - // The name __cplusplus is defined to the value 201103L when compiling a - // C++ translation unit. + // [C++11] The name __cplusplus is defined to the value 201103L when + // compiling a C++ translation unit. else if (LangOpts.CPlusPlus11) Builder.defineMacro("__cplusplus", "201103L"); - // C++03 [cpp.predefined]p1: - // The name __cplusplus is defined to the value 199711L when compiling a - // C++ translation unit. + // [C++03] The name __cplusplus is defined to the value 199711L when + // compiling a C++ translation unit. else Builder.defineMacro("__cplusplus", "199711L"); - // C++1z [cpp.predefined]p1: - // An integer literal of type std::size_t whose value is the alignment - // guaranteed by a call to operator new(std::size_t) + // -- __STDCPP_DEFAULT_NEW_ALIGNMENT__ + // [C++17] An integer literal of type std::size_t whose value is the + // alignment guaranteed by a call to operator new(std::size_t) // // We provide this in all language modes, since it seems generally useful. Builder.defineMacro("__STDCPP_DEFAULT_NEW_ALIGNMENT__", diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index c59b1372e399a..68160bc59eb6a 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -80,7 +80,7 @@ class IndexingDeclVisitor : public ConstDeclVisitor { !MD->isSynthesizedAccessorStub(); } - + void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = nullptr, bool isIBType = false) { @@ -90,6 +90,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor { Parent->getLexicalDeclContext(), /*isBase=*/false, isIBType); IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); + auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm, + const NamedDecl *Parent) { + if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() && + !Parm->hasUnparsedDefaultArg()) + IndexCtx.indexBody(Parm->getDefaultArg(), Parent); + }; if (IndexCtx.shouldIndexFunctionLocalSymbols()) { if (const ParmVarDecl *Parm = dyn_cast(D)) { auto *DC = Parm->getDeclContext(); @@ -106,7 +112,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor { } else if (const FunctionDecl *FD = dyn_cast(D)) { if (IndexCtx.shouldIndexParametersInDeclarations() || FD->isThisDeclarationADefinition()) { - for (auto PI : FD->parameters()) { + for (const auto *PI : FD->parameters()) { + IndexDefaultParmeterArgument(PI, D); IndexCtx.handleDecl(PI); } } @@ -116,9 +123,7 @@ class IndexingDeclVisitor : public ConstDeclVisitor { if (const auto *FD = dyn_cast(D)) { if (FD->isThisDeclarationADefinition()) { for (const auto *PV : FD->parameters()) { - if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && - !PV->hasUnparsedDefaultArg()) - IndexCtx.indexBody(PV->getDefaultArg(), D); + IndexDefaultParmeterArgument(PV, D); } } } diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp index a7c37e8528d1b..784a6008575b5 100644 --- a/clang/lib/Index/IndexingContext.cpp +++ b/clang/lib/Index/IndexingContext.cpp @@ -169,6 +169,10 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { } switch (TKind) { case TSK_Undeclared: + // Instantiation maybe not happen yet when we see a SpecializationDecl, + // e.g. when the type doesn't need to be complete, we still treat it as an + // instantiation as we'd like to keep the canonicalized result consistent. + return isa(D); case TSK_ExplicitSpecialization: return false; case TSK_ImplicitInstantiation: @@ -206,7 +210,12 @@ getDeclContextForTemplateInstationPattern(const Decl *D) { static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { if (const ClassTemplateSpecializationDecl * SD = dyn_cast(D)) { - return SD->getTemplateInstantiationPattern(); + const auto *Template = SD->getTemplateInstantiationPattern(); + if (Template) + return Template; + // Fallback to primary template if no instantiation is available yet (e.g. + // the type doesn't need to be complete). + return SD->getSpecializedTemplate()->getTemplatedDecl(); } else if (const FunctionDecl *FD = dyn_cast(D)) { return FD->getTemplateInstantiationPattern(); } else if (auto *VD = dyn_cast(D)) { diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 79434bc16ec3c..a19bf2ca8b5bc 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1006,7 +1006,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -2735,7 +2735,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get()); ExprResult SubExpr = ParseCastExpression(AnyCastExpr); - + if (Ty.isInvalid() || SubExpr.isInvalid()) return ExprError(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 550bf70454254..10608644a8fe9 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1302,7 +1302,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( ParseParameterDeclarationClause(D.getContext(), Attr, ParamInfo, EllipsisLoc); - // For a generic lambda, each 'auto' within the parameter declaration + // For a generic lambda, each 'auto' within the parameter declaration // clause creates a template type parameter, so increment the depth. // If we've parsed any explicit template parameters, then the depth will // have already been incremented. So we make sure that at most a single diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index ea2c871d6a829..b596aded867da 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -781,12 +781,6 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); - if (!AteExtraColon && isGotoAsm && Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_asm_goto_cannot_have_output); - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 8debebc7702ac..53c4829f43f4e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -986,7 +986,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // Create the parameter. return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl, - Depth, Position, EqualLoc, + Depth, Position, EqualLoc, DefaultArg.get()); } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index e0fbaab4d03f6..ce463beeddb2e 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -186,21 +186,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { ConsumeToken(); // Skip attributes. - while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec, - tok::kw_alignas)) { - if (Tok.is(tok::l_square)) { - ConsumeBracket(); - if (!SkipUntil(tok::r_square)) - return TPResult::Error; - } else { - ConsumeToken(); - if (Tok.isNot(tok::l_paren)) - return TPResult::Error; - ConsumeParen(); - if (!SkipUntil(tok::r_paren)) - return TPResult::Error; - } - } + if (!TrySkipAttributes()) + return TPResult::Error; if (TryAnnotateOptionalCXXScopeToken()) return TPResult::Error; @@ -781,6 +768,32 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, return CAK_NotAttributeSpecifier; } +bool Parser::TrySkipAttributes() { + while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec, + tok::kw_alignas)) { + if (Tok.is(tok::l_square)) { + ConsumeBracket(); + if (Tok.isNot(tok::l_square)) + return false; + ConsumeBracket(); + if (!SkipUntil(tok::r_square) || Tok.isNot(tok::r_square)) + return false; + // Note that explicitly checking for `[[` and `]]` allows to fail as + // expected in the case of the Objective-C message send syntax. + ConsumeBracket(); + } else { + ConsumeToken(); + if (Tok.isNot(tok::l_paren)) + return false; + ConsumeParen(); + if (!SkipUntil(tok::r_paren)) + return false; + } + } + + return true; +} + Parser::TPResult Parser::TryParsePtrOperatorSeq() { while (true) { if (TryAnnotateOptionalCXXScopeToken(true)) @@ -790,9 +803,14 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { // ptr-operator ConsumeAnyToken(); + + // Skip attributes. + if (!TrySkipAttributes()) + return TPResult::Error; + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, tok::kw__Nonnull, tok::kw__Nullable, - tok::kw__Null_unspecified)) + tok::kw__Null_unspecified, tok::kw__Atomic)) ConsumeToken(); } else { return TPResult::True; diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 6d9f50e8c4b64..75255f990d80e 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -9,6 +9,7 @@ if (MSVC) set_source_files_properties(SemaExprCXX.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaSYCL.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaTemplate.cpp PROPERTIES COMPILE_FLAGS /bigobj) + set_source_files_properties(SemaTemplateDeduction.cpp PROPERTIES COMPILE_FLAGS /bigobj) endif() clang_tablegen(OpenCLBuiltins.inc -gen-clang-opencl-builtins diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index 888978dfdbd3e..f79bb54a81434 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -66,6 +66,12 @@ def FuncExtKhrGlMsaaSharing : FunctionExtension<"cl_khr_gl_msaa_sha // Multiple extensions def FuncExtKhrMipmapWritesAndWrite3d : FunctionExtension<"cl_khr_mipmap_image_writes cl_khr_3d_image_writes">; +// Arm extensions. +def ArmIntegerDotProductInt8 : FunctionExtension<"cl_arm_integer_dot_product_int8">; +def ArmIntegerDotProductAccumulateInt8 : FunctionExtension<"cl_arm_integer_dot_product_accumulate_int8">; +def ArmIntegerDotProductAccumulateInt16 : FunctionExtension<"cl_arm_integer_dot_product_accumulate_int16">; +def ArmIntegerDotProductAccumulateSaturateInt8 : FunctionExtension<"cl_arm_integer_dot_product_accumulate_saturate_int8">; + // Qualified Type. These map to ASTContext::QualType. class QualType { // Name of the field or function in a clang::ASTContext @@ -372,7 +378,11 @@ foreach RType = [Float, Double, Half, Char, UChar, Short, UShort, Int, UInt, Long, ULong] in { foreach IType = [Float, Double, Half, Char, UChar, Short, UShort, Int, UInt, Long, ULong] in { - foreach sat = ["", "_sat"] in { + // Conversions to integer type have a sat and non-sat variant. + foreach sat = !cond(!eq(RType.Name, "float") : [""], + !eq(RType.Name, "double") : [""], + !eq(RType.Name, "half") : [""], + 1 : ["", "_sat"]) in { foreach rnd = ["", "_rte", "_rtn", "_rtp", "_rtz"] in { def : Builtin<"convert_" # RType.Name # sat # rnd, [RType, IType], Attr.Const>; @@ -1350,3 +1360,30 @@ let Extension = FuncExtKhrGlMsaaSharing in { def : Builtin<"get_image_array_size", [Size, ImageType], Attr.Const>; } } + +//-------------------------------------------------------------------- +// Arm extensions. +let Extension = ArmIntegerDotProductInt8 in { + foreach name = ["arm_dot"] in { + def : Builtin, VectorType]>; + def : Builtin, VectorType]>; + } +} +let Extension = ArmIntegerDotProductAccumulateInt8 in { + foreach name = ["arm_dot_acc"] in { + def : Builtin, VectorType, UInt]>; + def : Builtin, VectorType, Int]>; + } +} +let Extension = ArmIntegerDotProductAccumulateInt16 in { + foreach name = ["arm_dot_acc"] in { + def : Builtin, VectorType, UInt]>; + def : Builtin, VectorType, Int]>; + } +} +let Extension = ArmIntegerDotProductAccumulateSaturateInt8 in { + foreach name = ["arm_dot_acc_sat"] in { + def : Builtin, VectorType, UInt]>; + def : Builtin, VectorType, Int]>; + } +} diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 21590d0e1a5ee..904ece5aa4831 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "UsedDeclVisitor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/DeclCXX.h" @@ -976,7 +975,9 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) { MarkDevice(); } - emitDeferredDiags(); + // Finalize analysis of OpenMP-specific constructs. + if (LangOpts.OpenMP) + finalizeOpenMPDelayedAnalysis(); assert(LateParsedInstantiations.empty() && "end of TU template instantiation should not create more " @@ -1471,129 +1472,27 @@ static void emitCallStackNotes(Sema &S, FunctionDecl *FD) { // Emit any deferred diagnostics for FD and erase them from the map in which // they're stored. -void Sema::emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack) { - auto It = DeviceDeferredDiags.find(FD); - if (It == DeviceDeferredDiags.end()) +static void emitDeferredDiags(Sema &S, FunctionDecl *FD, bool ShowCallStack) { + auto It = S.DeviceDeferredDiags.find(FD); + if (It == S.DeviceDeferredDiags.end()) return; bool HasWarningOrError = false; for (PartialDiagnosticAt &PDAt : It->second) { const SourceLocation &Loc = PDAt.first; const PartialDiagnostic &PD = PDAt.second; - HasWarningOrError |= getDiagnostics().getDiagnosticLevel( + HasWarningOrError |= S.getDiagnostics().getDiagnosticLevel( PD.getDiagID(), Loc) >= DiagnosticsEngine::Warning; - DiagnosticBuilder Builder(Diags.Report(Loc, PD.getDiagID())); + DiagnosticBuilder Builder(S.Diags.Report(Loc, PD.getDiagID())); Builder.setForceEmit(); PD.Emit(Builder); } - DeviceDeferredDiags.erase(It); + S.DeviceDeferredDiags.erase(It); // FIXME: Should this be called after every warning/error emitted in the loop // above, instead of just once per function? That would be consistent with // how we handle immediate errors, but it also seems like a bit much. if (HasWarningOrError && ShowCallStack) - emitCallStackNotes(*this, FD); -} - -namespace { -/// Helper class that emits deferred diagnostic messages if an entity directly -/// or indirectly using the function that causes the deferred diagnostic -/// messages is known to be emitted. -class DeferredDiagnosticsEmitter - : public UsedDeclVisitor { -public: - typedef UsedDeclVisitor Inherited; - llvm::SmallSet, 4> Visited; - llvm::SmallVector, 4> UseStack; - bool ShouldEmit; - unsigned InOMPDeviceContext; - - DeferredDiagnosticsEmitter(Sema &S) - : Inherited(S), ShouldEmit(false), InOMPDeviceContext(0) {} - - void VisitDeclRefExpr(DeclRefExpr *E) { - if (FunctionDecl *FD = dyn_cast(E->getDecl())) { - visitUsedDecl(E->getLocation(), FD); - } - } - - void VisitMemberExpr(MemberExpr *E) { - if (FunctionDecl *FD = dyn_cast(E->getMemberDecl())) - visitUsedDecl(E->getMemberLoc(), FD); - } - - void VisitOMPTargetDirective(OMPTargetDirective *Node) { - ++InOMPDeviceContext; - Inherited::VisitOMPTargetDirective(Node); - --InOMPDeviceContext; - } - - void VisitCapturedStmt(CapturedStmt *Node) { - visitUsedDecl(Node->getBeginLoc(), Node->getCapturedDecl()); - Inherited::VisitCapturedStmt(Node); - } - - void visitUsedDecl(SourceLocation Loc, Decl *D) { - if (auto *TD = dyn_cast(D)) { - for (auto *DD : TD->decls()) { - visitUsedDecl(Loc, DD); - } - } else if (auto *FTD = dyn_cast(D)) { - for (auto *DD : FTD->specializations()) { - visitUsedDecl(Loc, DD); - } - } else if (auto *FD = dyn_cast(D)) { - FunctionDecl *Caller = UseStack.empty() ? nullptr : UseStack.back(); - auto IsKnownEmitted = S.getEmissionStatus(FD, /*Final=*/true) == - Sema::FunctionEmissionStatus::Emitted; - if (!Caller) - ShouldEmit = IsKnownEmitted; - if ((!ShouldEmit && !S.getLangOpts().OpenMP && !Caller) || - S.shouldIgnoreInHostDeviceCheck(FD) || Visited.count(D)) - return; - // Finalize analysis of OpenMP-specific constructs. - if (Caller && S.LangOpts.OpenMP && UseStack.size() == 1) - S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc); - if (Caller) - S.DeviceKnownEmittedFns[FD] = {Caller, Loc}; - if (ShouldEmit || InOMPDeviceContext) - S.emitDeferredDiags(FD, Caller); - Visited.insert(D); - UseStack.push_back(FD); - if (auto *S = FD->getBody()) { - this->Visit(S); - } - UseStack.pop_back(); - Visited.erase(D); - } else if (auto *RD = dyn_cast(D)) { - for (auto *DD : RD->decls()) { - visitUsedDecl(Loc, DD); - } - } else if (auto *CD = dyn_cast(D)) { - if (auto *S = CD->getBody()) { - this->Visit(S); - } - } else if (auto *VD = dyn_cast(D)) { - if (auto *Init = VD->getInit()) { - auto DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD); - bool IsDev = DevTy && (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any); - if (IsDev) - ++InOMPDeviceContext; - this->Visit(Init); - if (IsDev) - --InOMPDeviceContext; - } - } - } -}; -} // namespace - -void Sema::emitDeferredDiags() { - if (DeviceDeferredDiags.empty() && !LangOpts.OpenMP) - return; - - DeferredDiagnosticsEmitter(*this).visitUsedDecl( - SourceLocation(), Context.getTranslationUnitDecl()); + emitCallStackNotes(S, FD); } // In CUDA, there are some constructs which may appear in semantically-valid @@ -1666,6 +1565,71 @@ Sema::DeviceDiagBuilder::~DeviceDiagBuilder() { } } +// Indicate that this function (and thus everything it transtively calls) will +// be codegen'ed, and emit any deferred diagnostics on this function and its +// (transitive) callees. +void Sema::markKnownEmitted( + Sema &S, FunctionDecl *OrigCaller, FunctionDecl *OrigCallee, + SourceLocation OrigLoc, + const llvm::function_ref IsKnownEmitted) { + // Nothing to do if we already know that FD is emitted. + if (IsKnownEmitted(S, OrigCallee)) { + assert(!S.DeviceCallGraph.count(OrigCallee)); + return; + } + + // We've just discovered that OrigCallee is known-emitted. Walk our call + // graph to see what else we can now discover also must be emitted. + + struct CallInfo { + FunctionDecl *Caller; + FunctionDecl *Callee; + SourceLocation Loc; + }; + llvm::SmallVector Worklist = {{OrigCaller, OrigCallee, OrigLoc}}; + llvm::SmallSet, 4> Seen; + Seen.insert(OrigCallee); + while (!Worklist.empty()) { + CallInfo C = Worklist.pop_back_val(); + assert(!IsKnownEmitted(S, C.Callee) && + "Worklist should not contain known-emitted functions."); + S.DeviceKnownEmittedFns[C.Callee] = {C.Caller, C.Loc}; + emitDeferredDiags(S, C.Callee, C.Caller); + + // If this is a template instantiation, explore its callgraph as well: + // Non-dependent calls are part of the template's callgraph, while dependent + // calls are part of to the instantiation's call graph. + if (auto *Templ = C.Callee->getPrimaryTemplate()) { + FunctionDecl *TemplFD = Templ->getAsFunction(); + if (!Seen.count(TemplFD) && !S.DeviceKnownEmittedFns.count(TemplFD)) { + Seen.insert(TemplFD); + Worklist.push_back( + {/* Caller = */ C.Caller, /* Callee = */ TemplFD, C.Loc}); + } + } + + // Add all functions called by Callee to our worklist. + auto CGIt = S.DeviceCallGraph.find(C.Callee); + if (CGIt == S.DeviceCallGraph.end()) + continue; + + for (std::pair, SourceLocation> FDLoc : + CGIt->second) { + FunctionDecl *NewCallee = FDLoc.first; + SourceLocation CallLoc = FDLoc.second; + if (Seen.count(NewCallee) || IsKnownEmitted(S, NewCallee)) + continue; + Seen.insert(NewCallee); + Worklist.push_back( + {/* Caller = */ C.Callee, /* Callee = */ NewCallee, CallLoc}); + } + + // C.Callee is now known-emitted, so we no longer need to maintain its list + // of callees in DeviceCallGraph. + S.DeviceCallGraph.erase(CGIt); + } +} + Sema::DeviceDiagBuilder Sema::targetDiag(SourceLocation Loc, unsigned DiagID) { if (LangOpts.OpenMP) return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 13b72c4c8574c..0c61057e10726 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -674,6 +674,25 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { // Otherwise, mark the call in our call graph so we can traverse it later. bool CallerKnownEmitted = getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted; + if (CallerKnownEmitted) { + // Host-side references to a __global__ function refer to the stub, so the + // function itself is never emitted and therefore should not be marked. + if (!shouldIgnoreInHostDeviceCheck(Callee)) + markKnownEmitted( + *this, Caller, Callee, Loc, [](Sema &S, FunctionDecl *FD) { + return S.getEmissionStatus(FD) == FunctionEmissionStatus::Emitted; + }); + } else { + // If we have + // host fn calls kernel fn calls host+device, + // the HD function does not get instantiated on the host. We model this by + // omitting at the call to the kernel from the callgraph. This ensures + // that, when compiling for host, only HD functions actually called from the + // host get marked as known-emitted. + if (!shouldIgnoreInHostDeviceCheck(Callee)) + DeviceCallGraph[Caller].insert({Callee, Loc}); + } + DeviceDiagBuilder::Kind DiagKind = [this, Caller, Callee, CallerKnownEmitted] { switch (IdentifyCUDAPreference(Caller, Callee)) { diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index a89cc4be53aa4..2b3b60e6bde46 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2764,7 +2764,8 @@ void CastOperation::CheckCStyleCast() { } if ((Self.Context.getTypeSize(SrcType) > - Self.Context.getTypeSize(DestType))) { + Self.Context.getTypeSize(DestType)) && + !DestType->isBooleanType()) { // C 6.3.2.3p6: Any pointer type may be converted to an integer type. // Except as previously specified, the result is implementation-defined. // If the result cannot be represented in the integer type, the behavior diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 42678ba8398ba..612f49e2d3ff4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1867,6 +1867,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (CheckIntelFPGAMemBuiltinFunctionCall(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_frame_address: + case Builtin::BI__builtin_return_address: + if (SemaBuiltinConstantArgRange(TheCall, 0, 0, 0xFFFF)) + return ExprError(); + break; } // Since the target specific builtins for each arch overlap, only check those @@ -4023,11 +4028,9 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, if (!Arg->isValueDependent()) { llvm::APSInt I(64); if (Arg->isIntegerConstantExpr(I, Context)) { - if (!I.isPowerOf2()) { - Diag(Arg->getExprLoc(), diag::err_alignment_not_power_of_two) + if (!I.isPowerOf2()) + Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two) << Arg->getSourceRange(); - return; - } if (I > Sema::MaximumAlignment) Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 487ba46c20b6d..6ba404034a86b 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -8776,7 +8776,16 @@ void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { if (++Count == 2500) // If we happen to hit a huge directory, break; // bail out early so we're not too slow. StringRef Filename = llvm::sys::path::filename(It->path()); - switch (It->type()) { + + // To know whether a symlink should be treated as file or a directory, we + // have to stat it. This should be cheap enough as there shouldn't be many + // symlinks. + llvm::sys::fs::file_type Type = It->type(); + if (Type == llvm::sys::fs::file_type::symlink_file) { + if (auto FileStatus = FS.status(It->path())) + Type = FileStatus->getType(); + } + switch (Type) { case llvm::sys::fs::file_type::directory_file: // All entries in a framework directory must have a ".framework" suffix, // but the suffix does not appear in the source code's include/import. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cea2374de5632..fcda94912fe35 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -17939,15 +17939,11 @@ Decl *Sema::getObjCDeclContext() const { return (dyn_cast_or_null(CurContext)); } -Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, - bool Final) { +Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD) { // Templates are emitted when they're instantiated. if (FD->isDependentContext()) return FunctionEmissionStatus::TemplateDiscarded; - if (LangOpts.SYCLIsDevice && FD->hasAttr()) - return FunctionEmissionStatus::Emitted; - FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown; if (LangOpts.OpenMPIsDevice) { Optional DevTy = @@ -17955,10 +17951,8 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, if (DevTy.hasValue()) { if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host) OMPES = FunctionEmissionStatus::OMPDiscarded; - else if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) { + else if (DeviceKnownEmittedFns.count(FD) > 0) OMPES = FunctionEmissionStatus::Emitted; - } } } else if (LangOpts.OpenMP) { // In OpenMP 4.5 all the functions are host functions. @@ -17974,11 +17968,10 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, if (DevTy.hasValue()) { if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { OMPES = FunctionEmissionStatus::OMPDiscarded; - } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) + } else if (DeviceKnownEmittedFns.count(FD) > 0) { OMPES = FunctionEmissionStatus::Emitted; - } else if (Final) - OMPES = FunctionEmissionStatus::Emitted; + } + } } } if (OMPES == FunctionEmissionStatus::OMPDiscarded || @@ -18013,7 +18006,9 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, // Otherwise, the function is known-emitted if it's in our set of // known-emitted functions. - return FunctionEmissionStatus::Unknown; + return (DeviceKnownEmittedFns.count(FD) > 0) + ? FunctionEmissionStatus::Emitted + : FunctionEmissionStatus::Unknown; } bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c4bf353bf8246..d14bde81887f3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3869,71 +3869,6 @@ bool Sema::checkRangedIntegralArgument(Expr *E, const AttrType *TmpAttr, return false; } -template -void Sema::AddOneConstantValueAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *E) { - AttrType TmpAttr(Context, CI, E); - - if (!E->isValueDependent()) { - ExprResult ICE; - if (checkRangedIntegralArgument(E, &TmpAttr, ICE)) - return; - E = ICE.get(); - } - - if (IntelFPGAPrivateCopiesAttr::classof(&TmpAttr)) { - if (!D->hasAttr()) - D->addAttr(IntelFPGAMemoryAttr::CreateImplicit( - Context, IntelFPGAMemoryAttr::Default)); - } - - D->addAttr(::new (Context) AttrType(Context, CI, E)); -} - -template -void Sema::AddOneConstantPowerTwoValueAttr(Decl *D, - const AttributeCommonInfo &CI, - Expr *E) { - AttrType TmpAttr(Context, CI, E); - - if (!E->isValueDependent()) { - ExprResult ICE; - if (checkRangedIntegralArgument(E, &TmpAttr, ICE)) - return; - Expr::EvalResult Result; - E->EvaluateAsInt(Result, Context); - llvm::APSInt Value = Result.Val.getInt(); - if (!Value.isPowerOf2()) { - Diag(CI.getLoc(), diag::err_attribute_argument_not_power_of_two) - << &TmpAttr; - return; - } - if (IntelFPGANumBanksAttr::classof(&TmpAttr)) { - if (auto *BBA = D->getAttr()) { - unsigned NumBankBits = BBA->args_size(); - if (NumBankBits != Value.ceilLogBase2()) { - Diag(TmpAttr.getLocation(), diag::err_bankbits_numbanks_conflicting); - return; - } - } - } - E = ICE.get(); - } - - if (!D->hasAttr()) - D->addAttr(IntelFPGAMemoryAttr::CreateImplicit( - Context, IntelFPGAMemoryAttr::Default)); - - // We are adding a user NumBanks, drop any implicit default. - if (IntelFPGANumBanksAttr::classof(&TmpAttr)) { - if (auto *NBA = D->getAttr()) - if (NBA->isImplicit()) - D->dropAttr(); - } - - D->addAttr(::new (Context) AttrType(Context, CI, E)); -} - void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, bool IsPackExpansion) { AlignedAttr TmpAttr(Context, CI, true, E); @@ -5516,6 +5451,47 @@ static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); } +void Sema::addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &Attr, + Expr *E) { + VarDecl *VD = cast(D); + QualType Ty = VD->getType(); + // TODO: Applicable only on pipe storages. Currently they are defined + // as structures inside of SYCL headers. Add a check for pipe_storage_t + // when it is ready. + if (!Ty->isStructureType()) { + Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str) + << Attr.getAttrName() << "SYCL pipe storage declaration"; + return; + } + + if (!E->isInstantiationDependent()) { + llvm::APSInt ArgVal(32); + if (!E->isIntegerConstantExpr(ArgVal, getASTContext())) { + Diag(E->getExprLoc(), diag::err_attribute_argument_type) + << Attr.getAttrName() << AANT_ArgumentIntegerConstant + << E->getSourceRange(); + return; + } + int32_t ArgInt = ArgVal.getSExtValue(); + if (ArgInt < 0) { + Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) + << Attr.getAttrName() << /*non-negative*/ 1; + return; + } + } + + D->addAttr(::new (Context) SYCLIntelPipeIOAttr(Context, Attr, E)); +} + +static void handleSYCLIntelPipeIOAttr(Sema &S, Decl *D, + const ParsedAttr &Attr) { + if (D->isInvalidDecl()) + return; + + Expr *E = Attr.getArgAsExpr(0); + S.addSYCLIntelPipeIOAttr(D, Attr, E); +} + static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) { if (AliasName.startswith("__arm_")) AliasName = AliasName.substr(6); @@ -8040,6 +8016,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_IntelFPGABankBits: handleIntelFPGABankBitsAttr(S, D, AL); break; + case ParsedAttr::AT_SYCLIntelPipeIO: + handleSYCLIntelPipeIOAttr(S, D, AL); + break; case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: handleSimpleAttribute(S, D, AL); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7331c3369744c..5b13eb44169e1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -14684,6 +14684,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, MarkFunctionReferenced(ConstructLoc, Constructor); if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) return ExprError(); + if (getLangOpts().SYCLIsDevice) + checkSYCLDeviceFunction(ConstructLoc, Constructor); return CXXConstructExpr::Create( Context, DeclInitType, ConstructLoc, Constructor, Elidable, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 33b4b3f6c8c70..bbebd926d9b24 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "TreeTransform.h" -#include "UsedDeclVisitor.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" @@ -211,6 +210,15 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, bool ObjCPropertyAccess, bool AvoidPartialAvailabilityChecks, ObjCInterfaceDecl *ClassReceiver) { + if (getLangOpts().SYCLIsDevice) { + if (auto VD = dyn_cast(D)) { + if (VD->getStorageClass() == SC_Static && + !VD->getType().isConstant(Context)) + SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) + << Sema::KernelNonConstStaticDataVariable; + } + } + SourceLocation Loc = Locs.front(); if (getLangOpts().CPlusPlus && isa(D)) { // If there were any diagnostics suppressed by template argument deduction, @@ -292,6 +300,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD)) return true; + + if (getLangOpts().SYCLIsDevice) + checkSYCLDeviceFunction(Loc, FD); } if (auto *MD = dyn_cast(D)) { @@ -1916,7 +1927,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, bool RefersToCapturedVariable = isa(D) && NeedToCaptureVariable(cast(D), NameInfo.getLoc()); - + DeclRefExpr *E = DeclRefExpr::Create( Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty, VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D)); @@ -5258,7 +5269,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // Emit the location of the prototype. if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) - Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl; + Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl; return true; } @@ -5303,7 +5314,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // Emit the location of the prototype. if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) - Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl; + Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl; // This deletes the extra arguments. Call->shrinkNumArgs(NumParams); @@ -8208,11 +8219,13 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { } // General pointer incompatibility takes priority over qualifiers. + if (RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType()) + return Sema::IncompatibleFunctionPointer; return Sema::IncompatiblePointer; } if (!S.getLangOpts().CPlusPlus && S.IsFunctionConversion(ltrans, rtrans, ltrans)) - return Sema::IncompatiblePointer; + return Sema::IncompatibleFunctionPointer; return ConvTy; } @@ -14844,24 +14857,44 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, return false; case PointerToInt: - DiagKind = diag::ext_typecheck_convert_pointer_int; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_pointer_int; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_pointer_int; + } ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); MayHaveConvFixit = true; break; case IntToPointer: - DiagKind = diag::ext_typecheck_convert_int_pointer; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_int_pointer; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_int_pointer; + } + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; + break; + case IncompatibleFunctionPointer: + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_incompatible_function_pointer; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer; + } ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); MayHaveConvFixit = true; break; case IncompatiblePointer: - if (Action == AA_Passing_CFAudited) + if (Action == AA_Passing_CFAudited) { DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer; - else if (SrcType->isFunctionPointerType() && - DstType->isFunctionPointerType()) - DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer; - else + } else if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_incompatible_pointer; + isInvalid = true; + } else { DiagKind = diag::ext_typecheck_convert_incompatible_pointer; - + } CheckInferredResultType = DstType->isObjCObjectPointerType() && SrcType->isObjCObjectPointerType(); if (Hint.isNull() && !CheckInferredResultType) { @@ -14874,15 +14907,27 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, MayHaveConvFixit = true; break; case IncompatiblePointerSign: - DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_incompatible_pointer_sign; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; + } break; case FunctionVoidPointer: - DiagKind = diag::ext_typecheck_convert_pointer_void_func; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_pointer_void_func; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_pointer_void_func; + } break; case IncompatiblePointerDiscardsQualifiers: { // Perform array-to-pointer decay if necessary. if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType); + isInvalid = true; + Qualifiers lhq = SrcType->getPointeeType().getQualifiers(); Qualifiers rhq = DstType->getPointeeType().getQualifiers(); if (lhq.getAddressSpace() != rhq.getAddressSpace()) { @@ -14910,19 +14955,33 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (getLangOpts().CPlusPlus && IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType)) return false; - DiagKind = diag::ext_typecheck_convert_discards_qualifiers; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_typecheck_convert_discards_qualifiers; + isInvalid = true; + } else { + DiagKind = diag::ext_typecheck_convert_discards_qualifiers; + } + break; case IncompatibleNestedPointerQualifiers: - DiagKind = diag::ext_nested_pointer_qualifier_mismatch; + if (getLangOpts().CPlusPlus) { + isInvalid = true; + DiagKind = diag::err_nested_pointer_qualifier_mismatch; + } else { + DiagKind = diag::ext_nested_pointer_qualifier_mismatch; + } break; case IncompatibleNestedPointerAddressSpaceMismatch: DiagKind = diag::err_typecheck_incompatible_nested_address_space; + isInvalid = true; break; case IntToBlockPointer: DiagKind = diag::err_int_to_block_pointer; + isInvalid = true; break; case IncompatibleBlockPointer: DiagKind = diag::err_typecheck_convert_incompatible_block_pointer; + isInvalid = true; break; case IncompatibleObjCQualifiedId: { if (SrcType->isObjCQualifiedIdType()) { @@ -14947,14 +15006,25 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SrcType->castAs()->getInterfaceType()) IFace = IFaceT->getDecl(); } - DiagKind = diag::warn_incompatible_qualified_id; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_incompatible_qualified_id; + isInvalid = true; + } else { + DiagKind = diag::warn_incompatible_qualified_id; + } break; } case IncompatibleVectors: - DiagKind = diag::warn_incompatible_vectors; + if (getLangOpts().CPlusPlus) { + DiagKind = diag::err_incompatible_vectors; + isInvalid = true; + } else { + DiagKind = diag::warn_incompatible_vectors; + } break; case IncompatibleObjCWeakRef: DiagKind = diag::err_arc_weak_unavailable_assign; + isInvalid = true; break; case Incompatible: if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) { @@ -15012,9 +15082,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, HandleFunctionTypeMismatch(FDiag, SecondType, FirstType); Diag(Loc, FDiag); - if (DiagKind == diag::warn_incompatible_qualified_id && + if ((DiagKind == diag::warn_incompatible_qualified_id || + DiagKind == diag::err_incompatible_qualified_id) && PDecl && IFace && !IFace->hasDefinition()) - Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id) + Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id) << IFace << PDecl; if (SecondType == Context.OverloadTy) @@ -15820,6 +15891,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, if (getLangOpts().CUDA) CheckCUDACall(Loc, Func); + if (getLangOpts().SYCLIsDevice) + checkSYCLDeviceFunction(Loc, Func); // If we need a definition, try to create one. if (NeedDefinition && !Func->getBody()) { @@ -15962,8 +16035,13 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, Func->markUsed(Context); } - if (LangOpts.OpenMP) + if (LangOpts.OpenMP) { markOpenMPDeclareVariantFuncsReferenced(Loc, Func, MightBeOdrUse); + if (LangOpts.OpenMPIsDevice) + checkOpenMPDeviceFunction(Loc, Func); + else + checkOpenMPHostFunction(Loc, Func); + } } /// Directly mark a variable odr-used. Given a choice, prefer to use @@ -17355,33 +17433,71 @@ void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { } namespace { -/// Helper class that marks all of the declarations referenced by -/// potentially-evaluated subexpressions as "referenced". -class EvaluatedExprMarker : public UsedDeclVisitor { -public: - typedef UsedDeclVisitor Inherited; - bool SkipLocalVariables; + /// Helper class that marks all of the declarations referenced by + /// potentially-evaluated subexpressions as "referenced". + class EvaluatedExprMarker : public EvaluatedExprVisitor { + Sema &S; + bool SkipLocalVariables; - EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) - : Inherited(S), SkipLocalVariables(SkipLocalVariables) {} + public: + typedef EvaluatedExprVisitor Inherited; - void visitUsedDecl(SourceLocation Loc, Decl *D) { - S.MarkFunctionReferenced(Loc, cast(D)); - } + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) + : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } - void VisitDeclRefExpr(DeclRefExpr *E) { - // If we were asked not to visit local variables, don't. - if (SkipLocalVariables) { - if (VarDecl *VD = dyn_cast(E->getDecl())) - if (VD->hasLocalStorage()) - return; + void VisitDeclRefExpr(DeclRefExpr *E) { + // If we were asked not to visit local variables, don't. + if (SkipLocalVariables) { + if (VarDecl *VD = dyn_cast(E->getDecl())) + if (VD->hasLocalStorage()) + return; + } + + S.MarkDeclRefReferenced(E); } - S.MarkDeclRefReferenced(E); - } - void VisitMemberExpr(MemberExpr *E) { S.MarkMemberReferenced(E); } -}; -} // namespace + void VisitMemberExpr(MemberExpr *E) { + S.MarkMemberReferenced(E); + Inherited::VisitMemberExpr(E); + } + + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + S.MarkFunctionReferenced( + E->getBeginLoc(), + const_cast(E->getTemporary()->getDestructor())); + Visit(E->getSubExpr()); + } + + void VisitCXXNewExpr(CXXNewExpr *E) { + if (E->getOperatorNew()) + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew()); + if (E->getOperatorDelete()) + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete()); + Inherited::VisitCXXNewExpr(E); + } + + void VisitCXXDeleteExpr(CXXDeleteExpr *E) { + if (E->getOperatorDelete()) + S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete()); + QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); + if (const RecordType *DestroyedRec = Destroyed->getAs()) { + CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); + S.MarkFunctionReferenced(E->getBeginLoc(), S.LookupDestructor(Record)); + } + + Inherited::VisitCXXDeleteExpr(E); + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + S.MarkFunctionReferenced(E->getBeginLoc(), E->getConstructor()); + Inherited::VisitCXXConstructExpr(E); + } + + void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + Visit(E->getExpr()); + } + }; +} /// Mark any declarations that appear within this expression or any /// potentially-evaluated subexpressions as "referenced". diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 6ad87f6f9ddc0..85f226a723f86 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3926,9 +3926,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Cannot perform an ellipsis conversion"); case ImplicitConversionSequence::BadConversion: - bool Diagnosed = - DiagnoseAssignmentResult(Incompatible, From->getExprLoc(), ToType, - From->getType(), From, Action); + Sema::AssignConvertType ConvTy = + CheckAssignmentConstraints(From->getExprLoc(), ToType, From->getType()); + bool Diagnosed = DiagnoseAssignmentResult( + ConvTy == Compatible ? Incompatible : ConvTy, From->getExprLoc(), + ToType, From->getType(), From, Action); assert(Diagnosed && "failed to diagnose bad conversion"); (void)Diagnosed; return ExprError(); } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 305b14d55b333..9c7d8ecf7f9bb 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1456,7 +1456,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, PropertyLoc); PIDecl->setGetterMethodDecl(OMD); } - + if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // For Objective-C++, need to synthesize the AST for the IVAR object to be diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b6afabda578d4..e12bae2fd464b 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1710,6 +1710,92 @@ Sema::DeviceDiagBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); } +void Sema::checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckForDelayedContext) { + assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && + "Expected OpenMP device compilation."); + assert(Callee && "Callee may not be null."); + Callee = Callee->getMostRecentDecl(); + FunctionDecl *Caller = getCurFunctionDecl(); + + // host only function are not available on the device. + if (Caller) { + FunctionEmissionStatus CallerS = getEmissionStatus(Caller); + FunctionEmissionStatus CalleeS = getEmissionStatus(Callee); + assert(CallerS != FunctionEmissionStatus::CUDADiscarded && + CalleeS != FunctionEmissionStatus::CUDADiscarded && + "CUDADiscarded unexpected in OpenMP device function check"); + if ((CallerS == FunctionEmissionStatus::Emitted || + (!isOpenMPDeviceDelayedContext(*this) && + CallerS == FunctionEmissionStatus::Unknown)) && + CalleeS == FunctionEmissionStatus::OMPDiscarded) { + StringRef HostDevTy = getOpenMPSimpleClauseTypeName( + OMPC_device_type, OMPC_DEVICE_TYPE_host); + Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; + Diag(Callee->getAttr()->getLocation(), + diag::note_omp_marked_device_type_here) + << HostDevTy; + return; + } + } + // If the caller is known-emitted, mark the callee as known-emitted. + // Otherwise, mark the call in our call graph so we can traverse it later. + if ((CheckForDelayedContext && !isOpenMPDeviceDelayedContext(*this)) || + (!Caller && !CheckForDelayedContext) || + (Caller && getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted)) + markKnownEmitted(*this, Caller, Callee, Loc, + [CheckForDelayedContext](Sema &S, FunctionDecl *FD) { + return CheckForDelayedContext && + S.getEmissionStatus(FD) == + FunctionEmissionStatus::Emitted; + }); + else if (Caller) + DeviceCallGraph[Caller].insert({Callee, Loc}); +} + +void Sema::checkOpenMPHostFunction(SourceLocation Loc, FunctionDecl *Callee, + bool CheckCaller) { + assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && + "Expected OpenMP host compilation."); + assert(Callee && "Callee may not be null."); + Callee = Callee->getMostRecentDecl(); + FunctionDecl *Caller = getCurFunctionDecl(); + + // device only function are not available on the host. + if (Caller) { + FunctionEmissionStatus CallerS = getEmissionStatus(Caller); + FunctionEmissionStatus CalleeS = getEmissionStatus(Callee); + assert( + (LangOpts.CUDA || (CallerS != FunctionEmissionStatus::CUDADiscarded && + CalleeS != FunctionEmissionStatus::CUDADiscarded)) && + "CUDADiscarded unexpected in OpenMP host function check"); + if (CallerS == FunctionEmissionStatus::Emitted && + CalleeS == FunctionEmissionStatus::OMPDiscarded) { + StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( + OMPC_device_type, OMPC_DEVICE_TYPE_nohost); + Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; + Diag(Callee->getAttr()->getLocation(), + diag::note_omp_marked_device_type_here) + << NoHostDevTy; + return; + } + } + // If the caller is known-emitted, mark the callee as known-emitted. + // Otherwise, mark the call in our call graph so we can traverse it later. + if (!shouldIgnoreInHostDeviceCheck(Callee)) { + if ((!CheckCaller && !Caller) || + (Caller && + getEmissionStatus(Caller) == FunctionEmissionStatus::Emitted)) + markKnownEmitted( + *this, Caller, Callee, Loc, [CheckCaller](Sema &S, FunctionDecl *FD) { + return CheckCaller && + S.getEmissionStatus(FD) == FunctionEmissionStatus::Emitted; + }); + else if (Caller) + DeviceCallGraph[Caller].insert({Callee, Loc}); + } +} + void Sema::checkOpenMPDeviceExpr(const Expr *E) { assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && "OpenMP device compilation mode is expected."); @@ -2122,43 +2208,52 @@ bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } -void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, - const FunctionDecl *Callee, - SourceLocation Loc) { +void Sema::finalizeOpenMPDelayedAnalysis() { assert(LangOpts.OpenMP && "Expected OpenMP compilation mode."); - Optional DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl()); - // Ignore host functions during device analyzis. - if (LangOpts.OpenMPIsDevice && DevTy && - *DevTy == OMPDeclareTargetDeclAttr::DT_Host) - return; - // Ignore nohost functions during host analyzis. - if (!LangOpts.OpenMPIsDevice && DevTy && - *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) - return; - const FunctionDecl *FD = Callee->getMostRecentDecl(); - DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD); - if (LangOpts.OpenMPIsDevice && DevTy && - *DevTy == OMPDeclareTargetDeclAttr::DT_Host) { - // Diagnose host function called during device codegen. - StringRef HostDevTy = - getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); - Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; - Diag(FD->getAttr()->getLocation(), - diag::note_omp_marked_device_type_here) - << HostDevTy; - return; - } + // Diagnose implicit declare target functions and their callees. + for (const auto &CallerCallees : DeviceCallGraph) { + Optional DevTy = + OMPDeclareTargetDeclAttr::getDeviceType( + CallerCallees.getFirst()->getMostRecentDecl()); + // Ignore host functions during device analyzis. + if (LangOpts.OpenMPIsDevice && DevTy && + *DevTy == OMPDeclareTargetDeclAttr::DT_Host) + continue; + // Ignore nohost functions during host analyzis. + if (!LangOpts.OpenMPIsDevice && DevTy && + *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) + continue; + for (const std::pair, SourceLocation> + &Callee : CallerCallees.getSecond()) { + const FunctionDecl *FD = Callee.first->getMostRecentDecl(); + Optional DevTy = + OMPDeclareTargetDeclAttr::getDeviceType(FD); + if (LangOpts.OpenMPIsDevice && DevTy && + *DevTy == OMPDeclareTargetDeclAttr::DT_Host) { + // Diagnose host function called during device codegen. + StringRef HostDevTy = getOpenMPSimpleClauseTypeName( + OMPC_device_type, OMPC_DEVICE_TYPE_host); + Diag(Callee.second, diag::err_omp_wrong_device_function_call) + << HostDevTy << 0; + Diag(FD->getAttr()->getLocation(), + diag::note_omp_marked_device_type_here) + << HostDevTy; + continue; + } if (!LangOpts.OpenMPIsDevice && DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { // Diagnose nohost function called during host codegen. StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( OMPC_device_type, OMPC_DEVICE_TYPE_nohost); - Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; + Diag(Callee.second, diag::err_omp_wrong_device_function_call) + << NoHostDevTy << 1; Diag(FD->getAttr()->getLocation(), diag::note_omp_marked_device_type_here) << NoHostDevTy; + continue; } + } + } } void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, @@ -15336,256 +15431,282 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, return ConstLength.getSExtValue() != 1; } -// Return the expression of the base of the mappable expression or null if it -// cannot be determined and do all the necessary checks to see if the expression -// is valid as a standalone mappable expression. In the process, record all the -// components of the expression. -static const Expr *checkMapClauseExpressionBase( - Sema &SemaRef, Expr *E, - OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, - OpenMPClauseKind CKind, bool NoDiagnose) { - SourceLocation ELoc = E->getExprLoc(); - SourceRange ERange = E->getSourceRange(); - - // The base of elements of list in a map clause have to be either: - // - a reference to variable or field. - // - a member expression. - // - an array expression. - // - // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the - // reference to 'r'. - // - // If we have: - // - // struct SS { - // Bla S; - // foo() { - // #pragma omp target map (S.Arr[:12]); - // } - // } - // - // We want to retrieve the member expression 'this->S'; +// The base of elements of list in a map clause have to be either: +// - a reference to variable or field. +// - a member expression. +// - an array expression. +// +// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the +// reference to 'r'. +// +// If we have: +// +// struct SS { +// Bla S; +// foo() { +// #pragma omp target map (S.Arr[:12]); +// } +// } +// +// We want to retrieve the member expression 'this->S'; +// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.2] +// If a list item is an array section, it must specify contiguous storage. +// +// For this restriction it is sufficient that we make sure only references +// to variables or fields and array expressions, and that no array sections +// exist except in the rightmost expression (unless they cover the whole +// dimension of the array). E.g. these would be invalid: +// +// r.ArrS[3:5].Arr[6:7] +// +// r.ArrS[3:5].x +// +// but these would be valid: +// r.ArrS[3].Arr[6:7] +// +// r.ArrS[3].x +namespace { +class MapBaseChecker final : public StmtVisitor { + Sema &SemaRef; + OpenMPClauseKind CKind = OMPC_unknown; + OMPClauseMappableExprCommon::MappableExprComponentList &Components; + bool NoDiagnose = false; const Expr *RelevantExpr = nullptr; - - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.2] - // If a list item is an array section, it must specify contiguous storage. - // - // For this restriction it is sufficient that we make sure only references - // to variables or fields and array expressions, and that no array sections - // exist except in the rightmost expression (unless they cover the whole - // dimension of the array). E.g. these would be invalid: - // - // r.ArrS[3:5].Arr[6:7] - // - // r.ArrS[3:5].x - // - // but these would be valid: - // r.ArrS[3].Arr[6:7] - // - // r.ArrS[3].x - bool AllowUnitySizeArraySection = true; bool AllowWholeSizeArraySection = true; + SourceLocation ELoc; + SourceRange ERange; - while (!RelevantExpr) { - E = E->IgnoreParenImpCasts(); - - if (auto *CurE = dyn_cast(E)) { - if (!isa(CurE->getDecl())) - return nullptr; - - RelevantExpr = CurE; + void emitErrorMsg() { + if (!NoDiagnose) { + // If nothing else worked, this is not a valid map clause expression. + SemaRef.Diag(ELoc, diag::err_omp_expected_named_var_member_or_array_expression) + << ERange; + } + } - // If we got a reference to a declaration, we should not expect any array - // section before that. - AllowUnitySizeArraySection = false; - AllowWholeSizeArraySection = false; +public: + bool VisitDeclRefExpr(DeclRefExpr *DRE) { + if (!isa(DRE->getDecl())) { + emitErrorMsg(); + return false; + } + RelevantExpr = DRE; + // Record the component. + Components.emplace_back(DRE, DRE->getDecl()); + return true; + } - // Record the component. - CurComponents.emplace_back(CurE, CurE->getDecl()); - } else if (auto *CurE = dyn_cast(E)) { - Expr *BaseE = CurE->getBase()->IgnoreParenImpCasts(); + bool VisitMemberExpr(MemberExpr *ME) { + Expr *E = ME; + Expr *BaseE = ME->getBase()->IgnoreParenCasts(); - if (isa(BaseE)) - // We found a base expression: this->Val. - RelevantExpr = CurE; - else - E = BaseE; + if (isa(BaseE)) + // We found a base expression: this->Val. + RelevantExpr = ME; + else + E = BaseE; - if (!isa(CurE->getMemberDecl())) { - if (!NoDiagnose) { - SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field) - << CurE->getSourceRange(); - return nullptr; - } - if (RelevantExpr) - return nullptr; - continue; + if (!isa(ME->getMemberDecl())) { + if (!NoDiagnose) { + SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field) + << ME->getSourceRange(); + return false; } + if (RelevantExpr) + return false; + return Visit(E); + } - auto *FD = cast(CurE->getMemberDecl()); + auto *FD = cast(ME->getMemberDecl()); - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] - // A bit-field cannot appear in a map clause. - // - if (FD->isBitField()) { - if (!NoDiagnose) { - SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause) - << CurE->getSourceRange() << getOpenMPClauseName(CKind); - return nullptr; - } - if (RelevantExpr) - return nullptr; - continue; + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] + // A bit-field cannot appear in a map clause. + // + if (FD->isBitField()) { + if (!NoDiagnose) { + SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause) + << ME->getSourceRange() << getOpenMPClauseName(CKind); + return false; } + if (RelevantExpr) + return false; + return Visit(E); + } - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] - // If the type of a list item is a reference to a type T then the type - // will be considered to be T for all purposes of this clause. - QualType CurType = BaseE->getType().getNonReferenceType(); + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] + // If the type of a list item is a reference to a type T then the type + // will be considered to be T for all purposes of this clause. + QualType CurType = BaseE->getType().getNonReferenceType(); - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2] - // A list item cannot be a variable that is a member of a structure with - // a union type. - // - if (CurType->isUnionType()) { - if (!NoDiagnose) { - SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed) - << CurE->getSourceRange(); - return nullptr; - } - continue; + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2] + // A list item cannot be a variable that is a member of a structure with + // a union type. + // + if (CurType->isUnionType()) { + if (!NoDiagnose) { + SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed) + << ME->getSourceRange(); + return false; } + return RelevantExpr || Visit(E); + } - // If we got a member expression, we should not expect any array section - // before that: - // - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7] - // If a list item is an element of a structure, only the rightmost symbol - // of the variable reference can be an array section. - // - AllowUnitySizeArraySection = false; - AllowWholeSizeArraySection = false; + // If we got a member expression, we should not expect any array section + // before that: + // + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7] + // If a list item is an element of a structure, only the rightmost symbol + // of the variable reference can be an array section. + // + AllowUnitySizeArraySection = false; + AllowWholeSizeArraySection = false; - // Record the component. - CurComponents.emplace_back(CurE, FD); - } else if (auto *CurE = dyn_cast(E)) { - E = CurE->getBase()->IgnoreParenImpCasts(); + // Record the component. + Components.emplace_back(ME, FD); + return RelevantExpr || Visit(E); + } - if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) { - if (!NoDiagnose) { - SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) - << 0 << CurE->getSourceRange(); - return nullptr; - } - continue; + bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) { + Expr *E = AE->getBase()->IgnoreParenImpCasts(); + + if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) { + if (!NoDiagnose) { + SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) + << 0 << AE->getSourceRange(); + return false; } + return RelevantExpr || Visit(E); + } - // If we got an array subscript that express the whole dimension we - // can have any array expressions before. If it only expressing part of - // the dimension, we can only have unitary-size array expressions. - if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, - E->getType())) - AllowWholeSizeArraySection = false; + // If we got an array subscript that express the whole dimension we + // can have any array expressions before. If it only expressing part of + // the dimension, we can only have unitary-size array expressions. + if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, + E->getType())) + AllowWholeSizeArraySection = false; - if (const auto *TE = dyn_cast(E)) { - Expr::EvalResult Result; - if (CurE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext())) { - if (!Result.Val.getInt().isNullValue()) { - SemaRef.Diag(CurE->getIdx()->getExprLoc(), - diag::err_omp_invalid_map_this_expr); - SemaRef.Diag(CurE->getIdx()->getExprLoc(), - diag::note_omp_invalid_subscript_on_this_ptr_map); - } - } - RelevantExpr = TE; + if (const auto *TE = dyn_cast(E->IgnoreParenCasts())) { + Expr::EvalResult Result; + if (!AE->getIdx()->isValueDependent() && + AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) && + !Result.Val.getInt().isNullValue()) { + SemaRef.Diag(AE->getIdx()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(AE->getIdx()->getExprLoc(), + diag::note_omp_invalid_subscript_on_this_ptr_map); } + RelevantExpr = TE; + } - // Record the component - we don't have any declaration associated. - CurComponents.emplace_back(CurE, nullptr); - } else if (auto *CurE = dyn_cast(E)) { - assert(!NoDiagnose && "Array sections cannot be implicitly mapped."); - E = CurE->getBase()->IgnoreParenImpCasts(); + // Record the component - we don't have any declaration associated. + Components.emplace_back(AE, nullptr); - QualType CurType = - OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); + return RelevantExpr || Visit(E); + } - // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] - // If the type of a list item is a reference to a type T then the type - // will be considered to be T for all purposes of this clause. - if (CurType->isReferenceType()) - CurType = CurType->getPointeeType(); + bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) { + assert(!NoDiagnose && "Array sections cannot be implicitly mapped."); + Expr *E = OASE->getBase()->IgnoreParenImpCasts(); + QualType CurType = + OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); - bool IsPointer = CurType->isAnyPointerType(); + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] + // If the type of a list item is a reference to a type T then the type + // will be considered to be T for all purposes of this clause. + if (CurType->isReferenceType()) + CurType = CurType->getPointeeType(); - if (!IsPointer && !CurType->isArrayType()) { - SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) - << 0 << CurE->getSourceRange(); - return nullptr; - } + bool IsPointer = CurType->isAnyPointerType(); - bool NotWhole = - checkArrayExpressionDoesNotReferToWholeSize(SemaRef, CurE, CurType); - bool NotUnity = - checkArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType); + if (!IsPointer && !CurType->isArrayType()) { + SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) + << 0 << OASE->getSourceRange(); + return false; + } - if (AllowWholeSizeArraySection) { - // Any array section is currently allowed. Allowing a whole size array - // section implies allowing a unity array section as well. - // - // If this array section refers to the whole dimension we can still - // accept other array sections before this one, except if the base is a - // pointer. Otherwise, only unitary sections are accepted. - if (NotWhole || IsPointer) - AllowWholeSizeArraySection = false; - } else if (AllowUnitySizeArraySection && NotUnity) { - // A unity or whole array section is not allowed and that is not - // compatible with the properties of the current array section. - SemaRef.Diag( - ELoc, diag::err_array_section_does_not_specify_contiguous_storage) - << CurE->getSourceRange(); - return nullptr; - } + bool NotWhole = + checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType); + bool NotUnity = + checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType); - if (const auto *TE = dyn_cast(E)) { - Expr::EvalResult ResultR; - Expr::EvalResult ResultL; - if (CurE->getLength()->EvaluateAsInt(ResultR, - SemaRef.getASTContext())) { - if (!ResultR.Val.getInt().isOneValue()) { - SemaRef.Diag(CurE->getLength()->getExprLoc(), - diag::err_omp_invalid_map_this_expr); - SemaRef.Diag(CurE->getLength()->getExprLoc(), - diag::note_omp_invalid_length_on_this_ptr_mapping); - } - } - if (CurE->getLowerBound() && CurE->getLowerBound()->EvaluateAsInt( - ResultL, SemaRef.getASTContext())) { - if (!ResultL.Val.getInt().isNullValue()) { - SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), - diag::err_omp_invalid_map_this_expr); - SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), - diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); - } - } - RelevantExpr = TE; - } + if (AllowWholeSizeArraySection) { + // Any array section is currently allowed. Allowing a whole size array + // section implies allowing a unity array section as well. + // + // If this array section refers to the whole dimension we can still + // accept other array sections before this one, except if the base is a + // pointer. Otherwise, only unitary sections are accepted. + if (NotWhole || IsPointer) + AllowWholeSizeArraySection = false; + } else if (AllowUnitySizeArraySection && NotUnity) { + // A unity or whole array section is not allowed and that is not + // compatible with the properties of the current array section. + SemaRef.Diag( + ELoc, diag::err_array_section_does_not_specify_contiguous_storage) + << OASE->getSourceRange(); + return false; + } - // Record the component - we don't have any declaration associated. - CurComponents.emplace_back(CurE, nullptr); - } else { - if (!NoDiagnose) { - // If nothing else worked, this is not a valid map clause expression. - SemaRef.Diag( - ELoc, diag::err_omp_expected_named_var_member_or_array_expression) - << ERange; + if (const auto *TE = dyn_cast(E)) { + Expr::EvalResult ResultR; + Expr::EvalResult ResultL; + if (!OASE->getLength()->isValueDependent() && + OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) && + !ResultR.Val.getInt().isOneValue()) { + SemaRef.Diag(OASE->getLength()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(OASE->getLength()->getExprLoc(), + diag::note_omp_invalid_length_on_this_ptr_mapping); } - return nullptr; + if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() && + OASE->getLowerBound()->EvaluateAsInt(ResultL, + SemaRef.getASTContext()) && + !ResultL.Val.getInt().isNullValue()) { + SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), + diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); + } + RelevantExpr = TE; } + + // Record the component - we don't have any declaration associated. + Components.emplace_back(OASE, nullptr); + return RelevantExpr || Visit(E); + } + bool VisitStmt(Stmt *) { + emitErrorMsg(); + return false; + } + const Expr *getFoundBase() const { + return RelevantExpr; } + explicit MapBaseChecker( + Sema &SemaRef, OpenMPClauseKind CKind, + OMPClauseMappableExprCommon::MappableExprComponentList &Components, + bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange) + : SemaRef(SemaRef), CKind(CKind), Components(Components), + NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {} +}; +} // namespace - return RelevantExpr; +/// Return the expression of the base of the mappable expression or null if it +/// cannot be determined and do all the necessary checks to see if the expression +/// is valid as a standalone mappable expression. In the process, record all the +/// components of the expression. +static const Expr *checkMapClauseExpressionBase( + Sema &SemaRef, Expr *E, + OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, + OpenMPClauseKind CKind, bool NoDiagnose) { + SourceLocation ELoc = E->getExprLoc(); + SourceRange ERange = E->getSourceRange(); + MapBaseChecker Checker(SemaRef, CKind, CurComponents, NoDiagnose, ELoc, + ERange); + if (Checker.Visit(E->IgnoreParenImpCasts())) + return Checker.getFoundBase(); + return nullptr; } // Return true if expression E associated with value VD has conflicts with other @@ -17077,6 +17198,15 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, Diag(FD->getLocation(), diag::note_defined_here) << FD; return; } + // Mark the function as must be emitted for the device. + Optional DevTy = + OMPDeclareTargetDeclAttr::getDeviceType(FD); + if (LangOpts.OpenMPIsDevice && Res.hasValue() && IdLoc.isValid() && + *DevTy != OMPDeclareTargetDeclAttr::DT_Host) + checkOpenMPDeviceFunction(IdLoc, FD, /*CheckForDelayedContext=*/false); + if (!LangOpts.OpenMPIsDevice && Res.hasValue() && IdLoc.isValid() && + *DevTy != OMPDeclareTargetDeclAttr::DT_NoHost) + checkOpenMPHostFunction(IdLoc, FD, /*CheckCaller=*/false); } if (auto *VD = dyn_cast(D)) { // Problem if any with var declared with incomplete type will be reported diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index af257347d8823..d8bee50e3c82a 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -321,29 +321,16 @@ class MarkDeviceFunction : public RecursiveASTVisitor { return true; } - bool VisitMemberExpr(MemberExpr *E) { - if (VarDecl *VD = dyn_cast(E->getMemberDecl())) { - bool IsConst = VD->getType().getNonReferenceType().isConstQualified(); - if (!IsConst && VD->isStaticDataMember()) - SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) - << Sema::KernelNonConstStaticDataVariable; - } - return true; - } - bool VisitDeclRefExpr(DeclRefExpr *E) { - Decl* D = E->getDecl(); + Decl *D = E->getDecl(); if (SemaRef.isKnownGoodSYCLDecl(D)) return true; CheckSYCLType(E->getType(), E->getSourceRange()); if (VarDecl *VD = dyn_cast(D)) { bool IsConst = VD->getType().getNonReferenceType().isConstQualified(); - if (!IsConst && VD->isStaticDataMember()) - SemaRef.Diag(E->getExprLoc(), diag::err_sycl_restrict) - << Sema::KernelNonConstStaticDataVariable; - else if (!IsConst && VD->hasGlobalStorage() && !VD->isStaticLocal() && - !VD->isStaticDataMember() && !isa(VD)) { + if (!IsConst && VD->hasGlobalStorage() && !VD->isStaticLocal() && + !VD->isStaticDataMember() && !isa(VD)) { if (VD->getTLSKind() != VarDecl::TLS_None) SemaRef.Diag(E->getLocation(), diag::err_thread_unsupported); SemaRef.Diag(E->getLocation(), diag::err_sycl_restrict) @@ -1456,6 +1443,24 @@ Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc, return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this); } +void Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) { + assert(Callee && "Callee may not be null."); + + // Errors in unevaluated context don't need to be generated, + // so we can safely skip them. + if (isUnevaluatedContext()) + return; + + FunctionDecl *Caller = dyn_cast(getCurLexicalContext()); + + // If the caller is known-emitted, mark the callee as known-emitted. + // Otherwise, mark the call in our call graph so we can traverse it later. + if (Caller && isKnownEmitted(*this, Caller)) + markKnownEmitted(*this, Caller, Callee, Loc, isKnownEmitted); + else if (Caller) + DeviceCallGraph[Caller].insert({Callee, Loc}); +} + // ----------------------------------------------------------------------------- // Integration header functionality implementation // ----------------------------------------------------------------------------- diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 10f80d6c4fccd..b2b761d41779e 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -488,10 +488,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Look for the correct constraint index. unsigned ConstraintIdx = Piece.getOperandNo(); + unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); // Labels are the last in the Exprs list. - if (NS->isAsmGoto() && ConstraintIdx >= NS->getNumInputs()) + if (NS->isAsmGoto() && ConstraintIdx >= NumOperands) continue; - unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); // Look for the (ConstraintIdx - NumOperands + 1)th constraint with // modifier '+'. if (ConstraintIdx >= NumOperands) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1188017972cc2..c1084b875a92e 100755 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1288,11 +1288,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, // Check that we have valid decl-specifiers specified. auto CheckValidDeclSpecifiers = [this, &D] { // C++ [temp.param] - // p1 + // p1 // template-parameter: // ... // parameter-declaration - // p2 + // p2 // ... A storage class shall not be specified in a template-parameter // declaration. // [dcl.typedef]p1: @@ -8341,7 +8341,7 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, TemplateParameterLists.front(), ConstraintExpr); - + if (NewDecl->hasAssociatedConstraints()) { // C++2a [temp.concept]p4: // A concept shall not have associated constraints. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 005cbdd9b4cb8..9b6f4f4cbd2d6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -761,7 +761,7 @@ void Sema::PrintInstantiationStack() { case CodeSynthesisContext::Memoization: break; - + case CodeSynthesisContext::ConstraintsCheck: { unsigned DiagID = 0; if (!Active->Entity) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 70cd8e26bddfb..01019ed2e6aea 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -553,6 +553,17 @@ static void instantiateIntelFPGABankBitsAttr( S.AddIntelFPGABankBitsAttr(New, *Attr, Args.data(), Args.size()); } +static void instantiateSYCLIntelPipeIOAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const SYCLIntelPipeIOAttr *Attr, Decl *New) { + // The ID expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult Result = S.SubstExpr(Attr->getID(), TemplateArgs); + if (!Result.isInvalid()) + S.addSYCLIntelPipeIOAttr(New, *Attr, Result.getAs()); +} + void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -686,6 +697,10 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, instantiateIntelFPGABankBitsAttr(*this, TemplateArgs, IntelFPGABankBits, New); } + if (const auto *SYCLIntelPipeIO = dyn_cast(TmplAttr)) { + instantiateSYCLIntelPipeIOAttr(*this, TemplateArgs, SYCLIntelPipeIO, New); + continue; + } // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index d947d6d282be0..825b062c00543 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -940,7 +940,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { if (Expr *TRC = D.getTrailingRequiresClause()) if (TRC->containsUnexpandedParameterPack()) return true; - + return false; } diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h deleted file mode 100644 index 440029a1d567e..0000000000000 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- UsedDeclVisitor.h - ODR-used declarations visitor --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -//===----------------------------------------------------------------------===// -// -// This file defines UsedDeclVisitor, a CRTP class which visits all the -// declarations that are ODR-used by an expression or statement. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H -#define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H - -#include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/Sema/SemaInternal.h" - -namespace clang { -template -class UsedDeclVisitor : public EvaluatedExprVisitor { -protected: - Sema &S; - -public: - typedef EvaluatedExprVisitor Inherited; - - UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {} - - Derived &asImpl() { return *static_cast(this); } - - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - asImpl().visitUsedDecl( - E->getBeginLoc(), - const_cast(E->getTemporary()->getDestructor())); - asImpl().Visit(E->getSubExpr()); - } - - void VisitCXXNewExpr(CXXNewExpr *E) { - if (E->getOperatorNew()) - asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorNew()); - if (E->getOperatorDelete()) - asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); - Inherited::VisitCXXNewExpr(E); - } - - void VisitCXXDeleteExpr(CXXDeleteExpr *E) { - if (E->getOperatorDelete()) - asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); - QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); - if (const RecordType *DestroyedRec = Destroyed->getAs()) { - CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); - asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); - } - - Inherited::VisitCXXDeleteExpr(E); - } - - void VisitCXXConstructExpr(CXXConstructExpr *E) { - asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor()); - Inherited::VisitCXXConstructExpr(E); - } - - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - asImpl().Visit(E->getExpr()); - } -}; -} // end namespace clang - -#endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 7406c8795fe49..9b326d26eb845 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -436,7 +436,7 @@ bool ModuleManager::lookupModuleFile(StringRef FileName, // Open the file immediately to ensure there is no race between stat'ing and // opening the file. - auto FileOrErr = FileMgr.getFile(FileName, /*OpenFile=*/true, + auto FileOrErr = FileMgr.getFile(FileName, /*OpenFile=*/true, /*CacheFailure=*/false); if (!FileOrErr) { File = nullptr; diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 765c2f3e4530e..b7fb0d90c980c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -89,6 +89,7 @@ add_clang_library(clangStaticAnalyzerCheckers PointerSortingChecker.cpp PointerSubChecker.cpp PthreadLockChecker.cpp + cert/PutenvWithAutoChecker.cpp RetainCountChecker/RetainCountChecker.cpp RetainCountChecker/RetainCountDiagnostics.cpp ReturnPointerRangeChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h b/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h index 9642588d6a417..99731d6044a03 100644 --- a/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h +++ b/clang/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h @@ -11,13 +11,19 @@ #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_INTERCHECKERAPI_H #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_INTERCHECKERAPI_H -namespace clang { -class CheckerManager; +// FIXME: This file goes against how a checker should be implemented either in +// a single file, or be exposed in a header file. Let's try to get rid of it! + +namespace clang { namespace ento { +class CheckerManager; + /// Register the part of MallocChecker connected to InnerPointerChecker. void registerInnerPointerCheckerAux(CheckerManager &Mgr); -}} +} // namespace ento +} // namespace clang + #endif /* INTERCHECKERAPI_H_ */ diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp index 64daf358fbe59..e80d8bc32deca 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp @@ -200,22 +200,29 @@ ProgramStateRef advancePosition(ProgramStateRef State, const SVal &Iter, auto &SymMgr = State->getStateManager().getSymbolManager(); auto &SVB = State->getStateManager().getSValBuilder(); + auto &BVF = State->getStateManager().getBasicVals(); assert ((Op == OO_Plus || Op == OO_PlusEqual || Op == OO_Minus || Op == OO_MinusEqual) && "Advance operator must be one of +, -, += and -=."); auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub; - if (const auto IntDist = Distance.getAs()) { - // For concrete integers we can calculate the new position - const auto NewPos = - Pos->setTo(SVB.evalBinOp(State, BinOp, - nonloc::SymbolVal(Pos->getOffset()), - *IntDist, SymMgr.getType(Pos->getOffset())) - .getAsSymbol()); - return setIteratorPosition(State, Iter, NewPos); - } + const auto IntDistOp = Distance.getAs(); + if (!IntDistOp) + return nullptr; - return nullptr; + // For concrete integers we can calculate the new position + nonloc::ConcreteInt IntDist = *IntDistOp; + + if (IntDist.getValue().isNegative()) { + IntDist = nonloc::ConcreteInt(BVF.getValue(-IntDist.getValue())); + BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add; + } + const auto NewPos = + Pos->setTo(SVB.evalBinOp(State, BinOp, + nonloc::SymbolVal(Pos->getOffset()), + IntDist, SymMgr.getType(Pos->getOffset())) + .getAsSymbol()); + return setIteratorPosition(State, Iter, NewPos); } // This function tells the analyzer's engine that symbols produced by our diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 1d365bb727fdd..23b4abc670798 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -44,13 +44,14 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "AllocationState.h" #include "InterCheckerAPI.h" #include "clang/AST/Attr.h" #include "clang/AST/ParentMap.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -64,7 +65,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "AllocationState.h" +#include "llvm/Support/ErrorHandling.h" #include #include @@ -72,7 +73,10 @@ using namespace clang; using namespace ento; //===----------------------------------------------------------------------===// -// The types of allocation we're modeling. +// The types of allocation we're modeling. This is used to check whether a +// dynamically allocated object is deallocated with the correct function, like +// not using operator delete on an object created by malloc(), or alloca regions +// aren't ever deallocated manually. //===----------------------------------------------------------------------===// namespace { @@ -92,22 +96,14 @@ struct MemFunctionInfoTy; } // end of anonymous namespace -/// Determine family of a deallocation expression. -static AllocationFamily -getAllocationFamily(const MemFunctionInfoTy &MemFunctionInfo, CheckerContext &C, - const Stmt *S); - /// Print names of allocators and deallocators. /// /// \returns true on success. -static bool printAllocDeallocName(raw_ostream &os, CheckerContext &C, - const Expr *E); +static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E); -/// Print expected name of an allocator based on the deallocator's -/// family derived from the DeallocExpr. -static void printExpectedAllocName(raw_ostream &os, - const MemFunctionInfoTy &MemFunctionInfo, - CheckerContext &C, const Expr *E); +/// Print expected name of an allocator based on the deallocator's family +/// derived from the DeallocExpr. +static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family); /// Print expected name of a deallocator based on the allocator's /// family. @@ -208,7 +204,7 @@ static bool isReleased(SymbolRef Sym, CheckerContext &C); /// value; if unspecified, the value of expression \p E is used. static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State, - AllocationFamily Family = AF_Malloc, + AllocationFamily Family, Optional RetVal = None); //===----------------------------------------------------------------------===// @@ -272,8 +268,6 @@ REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair) namespace { -enum class MemoryOperationKind { MOK_Allocate, MOK_Free, MOK_Any }; - struct MemFunctionInfoTy { /// The value of the MallocChecker:Optimistic is stored in this variable. /// @@ -283,44 +277,41 @@ struct MemFunctionInfoTy { /// which might free a pointer are annotated. DefaultBool ShouldIncludeOwnershipAnnotatedFunctions; - // TODO: Change these to CallDescription, and get rid of lazy initialization. - mutable IdentifierInfo *II_alloca = nullptr, *II_win_alloca = nullptr, - *II_malloc = nullptr, *II_free = nullptr, - *II_realloc = nullptr, *II_calloc = nullptr, - *II_valloc = nullptr, *II_reallocf = nullptr, - *II_strndup = nullptr, *II_strdup = nullptr, - *II_win_strdup = nullptr, *II_kmalloc = nullptr, - *II_if_nameindex = nullptr, - *II_if_freenameindex = nullptr, *II_wcsdup = nullptr, - *II_win_wcsdup = nullptr, *II_g_malloc = nullptr, - *II_g_malloc0 = nullptr, *II_g_realloc = nullptr, - *II_g_try_malloc = nullptr, - *II_g_try_malloc0 = nullptr, - *II_g_try_realloc = nullptr, *II_g_free = nullptr, - *II_g_memdup = nullptr, *II_g_malloc_n = nullptr, - *II_g_malloc0_n = nullptr, *II_g_realloc_n = nullptr, - *II_g_try_malloc_n = nullptr, - *II_g_try_malloc0_n = nullptr, *II_kfree = nullptr, - *II_g_try_realloc_n = nullptr; - - void initIdentifierInfo(ASTContext &C) const; - - ///@{ - /// Check if this is one of the functions which can allocate/reallocate - /// memory pointed to by one of its arguments. - bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; - bool isCMemFunction(const FunctionDecl *FD, ASTContext &C, - AllocationFamily Family, - MemoryOperationKind MemKind) const; - - /// Tells if the callee is one of the builtin new/delete operators, including - /// placement operators and other standard overloads. - bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const; - ///@} + CallDescription CD_alloca{{"alloca"}, 1}, CD_win_alloca{{"_alloca"}, 1}, + CD_malloc{{"malloc"}, 1}, CD_BSD_malloc{{"malloc"}, 3}, + CD_free{{"free"}, 1}, CD_realloc{{"realloc"}, 2}, + CD_calloc{{"calloc"}, 2}, CD_valloc{{"valloc"}, 1}, + CD_reallocf{{"reallocf"}, 2}, CD_strndup{{"strndup"}, 2}, + CD_strdup{{"strdup"}, 1}, CD_win_strdup{{"_strdup"}, 1}, + CD_kmalloc{{"kmalloc"}, 2}, CD_if_nameindex{{"if_nameindex"}, 1}, + CD_if_freenameindex{{"if_freenameindex"}, 1}, CD_wcsdup{{"wcsdup"}, 1}, + CD_win_wcsdup{{"_wcsdup"}, 1}, CD_kfree{{"kfree"}, 2}, + CD_g_malloc{{"g_malloc"}, 1}, CD_g_malloc0{{"g_malloc0"}, 1}, + CD_g_realloc{{"g_realloc"}, 2}, CD_g_try_malloc{{"g_try_malloc"}, 1}, + CD_g_try_malloc0{{"g_try_malloc0"}, 1}, + CD_g_try_realloc{{"g_try_realloc"}, 2}, CD_g_free{{"g_free"}, 1}, + CD_g_memdup{{"g_memdup"}, 2}, CD_g_malloc_n{{"g_malloc_n"}, 2}, + CD_g_malloc0_n{{"g_malloc0_n"}, 2}, CD_g_realloc_n{{"g_realloc_n"}, 3}, + CD_g_try_malloc_n{{"g_try_malloc_n"}, 2}, + CD_g_try_malloc0_n{{"g_try_malloc0_n"}, 2}, + CD_g_try_realloc_n{{"g_try_realloc_n"}, 3}; + + bool isMemFunction(const CallEvent &Call) const; + bool isCMemFunction(const CallEvent &Call) const; + bool isCMemFreeFunction(const CallEvent &Call) const; + bool isCMemAllocFunction(const CallEvent &Call) const; }; - } // end of anonymous namespace +/// Tells if the callee is one of the builtin new/delete operators, including +/// placement operators and other standard overloads. +static bool isStandardNewDelete(const FunctionDecl *FD); +static bool isStandardNewDelete(const CallEvent &Call) { + if (!Call.getDecl()) + return false; + return isStandardNewDelete(cast(Call.getDecl())); +} + //===----------------------------------------------------------------------===// // Definition of the MallocChecker class. //===----------------------------------------------------------------------===// @@ -330,11 +321,10 @@ namespace { class MallocChecker : public Checker, - check::EndFunction, check::PreCall, - check::PostStmt, check::PostStmt, - check::NewAllocator, check::PreStmt, - check::PostStmt, check::PostObjCMessage, - check::Location, eval::Assume> { + check::EndFunction, check::PreCall, check::PostCall, + check::PostStmt, check::NewAllocator, + check::PreStmt, check::PostStmt, + check::PostObjCMessage, check::Location, eval::Assume> { public: MemFunctionInfoTy MemFunctionInfo; @@ -358,7 +348,7 @@ class MallocChecker CheckerNameRef CheckNames[CK_NumCheckKinds]; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; - void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; void checkNewAllocator(const CXXNewExpr *NE, SVal Target, CheckerContext &C) const; @@ -402,7 +392,7 @@ class MallocChecker /// Process C++ operator new()'s allocation, which is the part of C++ /// new-expression that goes before the constructor. void processNewAllocation(const CXXNewExpr *NE, CheckerContext &C, - SVal Target) const; + SVal Target, AllocationFamily Family) const; /// Perform a zero-allocation check. /// @@ -450,7 +440,7 @@ class MallocChecker static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, const Expr *SizeEx, SVal Init, ProgramStateRef State, - AllocationFamily Family = AF_Malloc); + AllocationFamily Family); /// Models memory allocation. /// @@ -464,7 +454,7 @@ class MallocChecker static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, SVal Size, SVal Init, ProgramStateRef State, - AllocationFamily Family = AF_Malloc); + AllocationFamily Family); static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE, ProgramStateRef State, SVal Target); @@ -518,6 +508,7 @@ class MallocChecker ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE, ProgramStateRef State, unsigned Num, bool Hold, bool &IsKnownToBeAllocated, + AllocationFamily Family, bool ReturnsNullOnFailure = false) const; /// Models memory deallocation. @@ -542,6 +533,7 @@ class MallocChecker ProgramStateRef FreeMemAux(CheckerContext &C, const Expr *ArgExpr, const Expr *ParentExpr, ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated, + AllocationFamily Family, bool ReturnsNullOnFailure = false) const; // TODO: Needs some refactoring, as all other deallocation modeling @@ -559,6 +551,7 @@ class MallocChecker /// \returns The ProgramState right after reallocation. ProgramStateRef ReallocMemAux(CheckerContext &C, const CallExpr *CE, bool ShouldFreeOnFail, ProgramStateRef State, + AllocationFamily Family, bool SuffixWithN = false) const; /// Evaluates the buffer size that needs to be allocated. @@ -623,9 +616,7 @@ class MallocChecker /// family/call/symbol. Optional getCheckIfTracked(AllocationFamily Family, bool IsALeakCheck = false) const; - Optional getCheckIfTracked(CheckerContext &C, - const Stmt *AllocDeallocStmt, - bool IsALeakCheck = false) const; + Optional getCheckIfTracked(CheckerContext &C, SymbolRef Sym, bool IsALeakCheck = false) const; ///@} @@ -633,17 +624,22 @@ class MallocChecker static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range, - const Expr *DeallocExpr) const; + const Expr *DeallocExpr, AllocationFamily Family) const; + void ReportFreeAlloca(CheckerContext &C, SVal ArgVal, SourceRange Range) const; + void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range, const Expr *DeallocExpr, const RefState *RS, SymbolRef Sym, bool OwnershipTransferred) const; + void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range, - const Expr *DeallocExpr, + const Expr *DeallocExpr, AllocationFamily Family, const Expr *AllocExpr = nullptr) const; + void ReportUseAfterFree(CheckerContext &C, SourceRange Range, SymbolRef Sym) const; + void ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released, SymbolRef Sym, SymbolRef PrevSym) const; @@ -653,7 +649,8 @@ class MallocChecker SymbolRef Sym) const; void ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, - SourceRange Range, const Expr *FreeExpr) const; + SourceRange Range, const Expr *FreeExpr, + AllocationFamily Family) const; /// Find the location of the allocation for Sym on the path leading to the /// exploded node N. @@ -801,6 +798,7 @@ REGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef) namespace { class StopTrackingCallback final : public SymbolVisitor { ProgramStateRef state; + public: StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {} ProgramStateRef getState() const { return state; } @@ -816,148 +814,81 @@ class StopTrackingCallback final : public SymbolVisitor { // Methods of MemFunctionInfoTy. //===----------------------------------------------------------------------===// -void MemFunctionInfoTy::initIdentifierInfo(ASTContext &Ctx) const { - if (II_malloc) - return; - II_alloca = &Ctx.Idents.get("alloca"); - II_malloc = &Ctx.Idents.get("malloc"); - II_free = &Ctx.Idents.get("free"); - II_realloc = &Ctx.Idents.get("realloc"); - II_reallocf = &Ctx.Idents.get("reallocf"); - II_calloc = &Ctx.Idents.get("calloc"); - II_valloc = &Ctx.Idents.get("valloc"); - II_strdup = &Ctx.Idents.get("strdup"); - II_strndup = &Ctx.Idents.get("strndup"); - II_wcsdup = &Ctx.Idents.get("wcsdup"); - II_kmalloc = &Ctx.Idents.get("kmalloc"); - II_kfree = &Ctx.Idents.get("kfree"); - II_if_nameindex = &Ctx.Idents.get("if_nameindex"); - II_if_freenameindex = &Ctx.Idents.get("if_freenameindex"); - - //MSVC uses `_`-prefixed instead, so we check for them too. - II_win_strdup = &Ctx.Idents.get("_strdup"); - II_win_wcsdup = &Ctx.Idents.get("_wcsdup"); - II_win_alloca = &Ctx.Idents.get("_alloca"); - - // Glib - II_g_malloc = &Ctx.Idents.get("g_malloc"); - II_g_malloc0 = &Ctx.Idents.get("g_malloc0"); - II_g_realloc = &Ctx.Idents.get("g_realloc"); - II_g_try_malloc = &Ctx.Idents.get("g_try_malloc"); - II_g_try_malloc0 = &Ctx.Idents.get("g_try_malloc0"); - II_g_try_realloc = &Ctx.Idents.get("g_try_realloc"); - II_g_free = &Ctx.Idents.get("g_free"); - II_g_memdup = &Ctx.Idents.get("g_memdup"); - II_g_malloc_n = &Ctx.Idents.get("g_malloc_n"); - II_g_malloc0_n = &Ctx.Idents.get("g_malloc0_n"); - II_g_realloc_n = &Ctx.Idents.get("g_realloc_n"); - II_g_try_malloc_n = &Ctx.Idents.get("g_try_malloc_n"); - II_g_try_malloc0_n = &Ctx.Idents.get("g_try_malloc0_n"); - II_g_try_realloc_n = &Ctx.Idents.get("g_try_realloc_n"); -} - -bool MemFunctionInfoTy::isMemFunction(const FunctionDecl *FD, - ASTContext &C) const { - if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any)) - return true; +bool MemFunctionInfoTy::isMemFunction(const CallEvent &Call) const { + return isCMemFunction(Call) || isStandardNewDelete(Call); +} - if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any)) - return true; +bool MemFunctionInfoTy::isCMemFunction(const CallEvent &Call) const { + return isCMemFreeFunction(Call) || isCMemAllocFunction(Call); +} - if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any)) +bool MemFunctionInfoTy::isCMemFreeFunction(const CallEvent &Call) const { + if (Call.isCalled(CD_free, CD_realloc, CD_reallocf, CD_g_free, CD_kfree)) return true; - if (isStandardNewDelete(FD, C)) + if (Call.isCalled(CD_if_freenameindex)) return true; - return false; -} - -bool MemFunctionInfoTy::isCMemFunction(const FunctionDecl *FD, ASTContext &C, - AllocationFamily Family, - MemoryOperationKind MemKind) const { - if (!FD) + if (!ShouldIncludeOwnershipAnnotatedFunctions) return false; - bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any || - MemKind == MemoryOperationKind::MOK_Free); - bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any || - MemKind == MemoryOperationKind::MOK_Allocate); - - if (FD->getKind() == Decl::Function) { - const IdentifierInfo *FunI = FD->getIdentifier(); - initIdentifierInfo(C); - - if (Family == AF_Malloc && CheckFree) { - if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf || - FunI == II_g_free || FunI == II_kfree) - return true; - } - - if (Family == AF_Malloc && CheckAlloc) { - if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf || - FunI == II_calloc || FunI == II_valloc || FunI == II_strdup || - FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup || - FunI == II_win_wcsdup || FunI == II_kmalloc || - FunI == II_g_malloc || FunI == II_g_malloc0 || - FunI == II_g_realloc || FunI == II_g_try_malloc || - FunI == II_g_try_malloc0 || FunI == II_g_try_realloc || - FunI == II_g_memdup || FunI == II_g_malloc_n || - FunI == II_g_malloc0_n || FunI == II_g_realloc_n || - FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n || - FunI == II_g_try_realloc_n) + const auto *Func = dyn_cast(Call.getDecl()); + if (Func && Func->hasAttrs()) { + for (const auto *I : Func->specific_attrs()) { + OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind(); + if (OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) return true; } + } + return false; +} - if (Family == AF_IfNameIndex && CheckFree) { - if (FunI == II_if_freenameindex) - return true; - } +bool MemFunctionInfoTy::isCMemAllocFunction(const CallEvent &Call) const { + if (Call.isCalled(CD_malloc, CD_realloc, CD_reallocf, CD_calloc, CD_valloc, + CD_strdup, CD_win_strdup, CD_strndup, CD_wcsdup, + CD_win_wcsdup, CD_kmalloc, CD_g_malloc, CD_g_malloc0, + CD_g_realloc, CD_g_try_malloc, CD_g_try_malloc0, + CD_g_try_realloc, CD_g_memdup, CD_g_malloc_n, + CD_g_malloc0_n, CD_g_realloc_n, CD_g_try_malloc_n, + CD_g_try_malloc0_n, CD_g_try_realloc_n)) + return true; - if (Family == AF_IfNameIndex && CheckAlloc) { - if (FunI == II_if_nameindex) - return true; - } + if (Call.isCalled(CD_if_nameindex)) + return true; - if (Family == AF_Alloca && CheckAlloc) { - if (FunI == II_alloca || FunI == II_win_alloca) - return true; - } - } + if (Call.isCalled(CD_alloca, CD_win_alloca)) + return true; - if (Family != AF_Malloc) + if (!ShouldIncludeOwnershipAnnotatedFunctions) return false; - if (ShouldIncludeOwnershipAnnotatedFunctions && FD->hasAttrs()) { - for (const auto *I : FD->specific_attrs()) { + const auto *Func = dyn_cast(Call.getDecl()); + if (Func && Func->hasAttrs()) { + for (const auto *I : Func->specific_attrs()) { OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind(); - if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) { - if (CheckFree) - return true; - } else if (OwnKind == OwnershipAttr::Returns) { - if (CheckAlloc) - return true; - } + if (OwnKind == OwnershipAttr::Returns) + return true; } } return false; } -bool MemFunctionInfoTy::isStandardNewDelete(const FunctionDecl *FD, - ASTContext &C) const { + +static bool isStandardNewDelete(const FunctionDecl *FD) { if (!FD) return false; OverloadedOperatorKind Kind = FD->getOverloadedOperator(); - if (Kind != OO_New && Kind != OO_Array_New && - Kind != OO_Delete && Kind != OO_Array_Delete) + if (Kind != OO_New && Kind != OO_Array_New && Kind != OO_Delete && + Kind != OO_Array_Delete) return false; // This is standard if and only if it's not defined in a user file. SourceLocation L = FD->getLocation(); // If the header for operator delete is not included, it's still defined // in an invalid source location. Check to make sure we don't crash. - return !L.isValid() || C.getSourceManager().isInSystemHeader(L); + return !L.isValid() || + FD->getASTContext().getSourceManager().isInSystemHeader(L); } //===----------------------------------------------------------------------===// @@ -1036,7 +967,7 @@ llvm::Optional MallocChecker::performKernelMalloc( // If M_ZERO is set, treat this like calloc (initialized). if (TrueState && !FalseState) { SVal ZeroVal = C.getSValBuilder().makeZeroVal(Ctx.CharTy); - return MallocMemAux(C, CE, CE->getArg(0), ZeroVal, TrueState); + return MallocMemAux(C, CE, CE->getArg(0), ZeroVal, TrueState, AF_Malloc); } return None; @@ -1053,10 +984,15 @@ SVal MallocChecker::evalMulForBufferSize(CheckerContext &C, const Expr *Blocks, return TotalSize; } -void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { +void MallocChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { if (C.wasInlined) return; + const auto *CE = dyn_cast_or_null(Call.getOriginExpr()); + if (!CE) + return; + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return; @@ -1065,21 +1001,19 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { bool IsKnownToBeAllocatedMemory = false; if (FD->getKind() == Decl::Function) { - MemFunctionInfo.initIdentifierInfo(C.getASTContext()); - IdentifierInfo *FunI = FD->getIdentifier(); - - if (FunI == MemFunctionInfo.II_malloc || - FunI == MemFunctionInfo.II_g_malloc || - FunI == MemFunctionInfo.II_g_try_malloc) { + if (Call.isCalled(MemFunctionInfo.CD_malloc, MemFunctionInfo.CD_BSD_malloc, + MemFunctionInfo.CD_g_malloc, + MemFunctionInfo.CD_g_try_malloc)) { switch (CE->getNumArgs()) { default: return; case 1: - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); + State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, + AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 0, State); break; case 2: - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); + llvm_unreachable("There shouldn't be a 2-argument malloc!"); break; case 3: llvm::Optional MaybeState = @@ -1087,57 +1021,60 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { if (MaybeState.hasValue()) State = MaybeState.getValue(); else - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); + State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, + AF_Malloc); break; } - } else if (FunI == MemFunctionInfo.II_kmalloc) { + } else if (Call.isCalled(MemFunctionInfo.CD_kmalloc)) { if (CE->getNumArgs() < 1) return; llvm::Optional MaybeState = - performKernelMalloc(CE, C, State); + performKernelMalloc(CE, C, State); if (MaybeState.hasValue()) State = MaybeState.getValue(); else - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); - } else if (FunI == MemFunctionInfo.II_valloc) { + State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, + AF_Malloc); + } else if (Call.isCalled(MemFunctionInfo.CD_valloc)) { if (CE->getNumArgs() < 1) return; - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); + State = + MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 0, State); - } else if (FunI == MemFunctionInfo.II_realloc || - FunI == MemFunctionInfo.II_g_realloc || - FunI == MemFunctionInfo.II_g_try_realloc) { - State = ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ false, State); + } else if (Call.isCalled(MemFunctionInfo.CD_realloc, + MemFunctionInfo.CD_g_realloc, + MemFunctionInfo.CD_g_try_realloc)) { + State = + ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ false, State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 1, State); - } else if (FunI == MemFunctionInfo.II_reallocf) { - State = ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ true, State); + } else if (Call.isCalled(MemFunctionInfo.CD_reallocf)) { + State = ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ true, State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 1, State); - } else if (FunI == MemFunctionInfo.II_calloc) { + } else if (Call.isCalled(MemFunctionInfo.CD_calloc)) { State = CallocMem(C, CE, State); State = ProcessZeroAllocCheck(C, CE, 0, State); State = ProcessZeroAllocCheck(C, CE, 1, State); - } else if (FunI == MemFunctionInfo.II_free || - FunI == MemFunctionInfo.II_g_free || - FunI == MemFunctionInfo.II_kfree) { + } else if (Call.isCalled(MemFunctionInfo.CD_free, MemFunctionInfo.CD_g_free, + MemFunctionInfo.CD_kfree)) { if (suppressDeallocationsInSuspiciousContexts(CE, C)) return; - State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory); - } else if (FunI == MemFunctionInfo.II_strdup || - FunI == MemFunctionInfo.II_win_strdup || - FunI == MemFunctionInfo.II_wcsdup || - FunI == MemFunctionInfo.II_win_wcsdup) { - State = MallocUpdateRefState(C, CE, State); - } else if (FunI == MemFunctionInfo.II_strndup) { - State = MallocUpdateRefState(C, CE, State); - } else if (FunI == MemFunctionInfo.II_alloca || - FunI == MemFunctionInfo.II_win_alloca) { + State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory, + AF_Malloc); + } else if (Call.isCalled( + MemFunctionInfo.CD_strdup, MemFunctionInfo.CD_win_strdup, + MemFunctionInfo.CD_wcsdup, MemFunctionInfo.CD_win_wcsdup)) { + State = MallocUpdateRefState(C, CE, State, AF_Malloc); + } else if (Call.isCalled(MemFunctionInfo.CD_strndup)) { + State = MallocUpdateRefState(C, CE, State, AF_Malloc); + } else if (Call.isCalled(MemFunctionInfo.CD_alloca, + MemFunctionInfo.CD_win_alloca)) { if (CE->getNumArgs() < 1) return; - State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, - AF_Alloca); + State = + MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, AF_Alloca); State = ProcessZeroAllocCheck(C, CE, 0, State); - } else if (MemFunctionInfo.isStandardNewDelete(FD, C.getASTContext())) { + } else if (isStandardNewDelete(FD)) { // Process direct calls to operator new/new[]/delete/delete[] functions // as distinct from new/new[]/delete/delete[] expressions that are // processed by the checkPostStmt callbacks for CXXNewExpr and @@ -1154,53 +1091,59 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { State = ProcessZeroAllocCheck(C, CE, 0, State); break; case OO_Delete: + State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory, + AF_CXXNew); + break; case OO_Array_Delete: - State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory); + State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory, + AF_CXXNewArray); break; default: llvm_unreachable("not a new/delete operator"); } - } else if (FunI == MemFunctionInfo.II_if_nameindex) { + } else if (Call.isCalled(MemFunctionInfo.CD_if_nameindex)) { // Should we model this differently? We can allocate a fixed number of // elements with zeros in the last one. State = MallocMemAux(C, CE, UnknownVal(), UnknownVal(), State, AF_IfNameIndex); - } else if (FunI == MemFunctionInfo.II_if_freenameindex) { - State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory); - } else if (FunI == MemFunctionInfo.II_g_malloc0 || - FunI == MemFunctionInfo.II_g_try_malloc0) { + } else if (Call.isCalled(MemFunctionInfo.CD_if_freenameindex)) { + State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory, + AF_IfNameIndex); + } else if (Call.isCalled(MemFunctionInfo.CD_g_malloc0, + MemFunctionInfo.CD_g_try_malloc0)) { if (CE->getNumArgs() < 1) return; SValBuilder &svalBuilder = C.getSValBuilder(); SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); - State = MallocMemAux(C, CE, CE->getArg(0), zeroVal, State); + State = MallocMemAux(C, CE, CE->getArg(0), zeroVal, State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 0, State); - } else if (FunI == MemFunctionInfo.II_g_memdup) { + } else if (Call.isCalled(MemFunctionInfo.CD_g_memdup)) { if (CE->getNumArgs() < 2) return; - State = MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), State); + State = + MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 1, State); - } else if (FunI == MemFunctionInfo.II_g_malloc_n || - FunI == MemFunctionInfo.II_g_try_malloc_n || - FunI == MemFunctionInfo.II_g_malloc0_n || - FunI == MemFunctionInfo.II_g_try_malloc0_n) { + } else if (Call.isCalled(MemFunctionInfo.CD_g_malloc_n, + MemFunctionInfo.CD_g_try_malloc_n, + MemFunctionInfo.CD_g_malloc0_n, + MemFunctionInfo.CD_g_try_malloc0_n)) { if (CE->getNumArgs() < 2) return; SVal Init = UndefinedVal(); - if (FunI == MemFunctionInfo.II_g_malloc0_n || - FunI == MemFunctionInfo.II_g_try_malloc0_n) { + if (Call.isCalled(MemFunctionInfo.CD_g_malloc0_n, + MemFunctionInfo.CD_g_try_malloc0_n)) { SValBuilder &SB = C.getSValBuilder(); Init = SB.makeZeroVal(SB.getContext().CharTy); } SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1)); - State = MallocMemAux(C, CE, TotalSize, Init, State); + State = MallocMemAux(C, CE, TotalSize, Init, State, AF_Malloc); State = ProcessZeroAllocCheck(C, CE, 0, State); State = ProcessZeroAllocCheck(C, CE, 1, State); - } else if (FunI == MemFunctionInfo.II_g_realloc_n || - FunI == MemFunctionInfo.II_g_try_realloc_n) { + } else if (Call.isCalled(MemFunctionInfo.CD_g_realloc_n, + MemFunctionInfo.CD_g_try_realloc_n)) { if (CE->getNumArgs() < 3) return; - State = ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ false, State, + State = ReallocMemAux(C, CE, /*ShouldFreeOnFail*/ false, State, AF_Malloc, /*SuffixWithN*/ true); State = ProcessZeroAllocCheck(C, CE, 1, State); State = ProcessZeroAllocCheck(C, CE, 2, State); @@ -1332,10 +1275,9 @@ static bool hasNonTrivialConstructorCall(const CXXNewExpr *NE) { } void MallocChecker::processNewAllocation(const CXXNewExpr *NE, - CheckerContext &C, - SVal Target) const { - if (!MemFunctionInfo.isStandardNewDelete(NE->getOperatorNew(), - C.getASTContext())) + CheckerContext &C, SVal Target, + AllocationFamily Family) const { + if (!isStandardNewDelete(NE->getOperatorNew())) return; const ParentMap &PM = C.getLocationContext()->getParentMap(); @@ -1352,8 +1294,7 @@ void MallocChecker::processNewAllocation(const CXXNewExpr *NE, // value (if any) and we don't want to loose this value. So we call // MallocUpdateRefState() instead of MallocMemAux() which breaks the // existing binding. - State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray - : AF_CXXNew, Target); + State = MallocUpdateRefState(C, NE, State, Family, Target); State = addExtentSize(C, NE, State, Target); State = ProcessZeroAllocCheck(C, NE, 0, State, Target); C.addTransition(State); @@ -1361,14 +1302,19 @@ void MallocChecker::processNewAllocation(const CXXNewExpr *NE, void MallocChecker::checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const { - if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator) - processNewAllocation(NE, C, C.getSVal(NE)); + if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator) { + if (NE->isArray()) + processNewAllocation(NE, C, C.getSVal(NE), + (NE->isArray() ? AF_CXXNewArray : AF_CXXNew)); + } } void MallocChecker::checkNewAllocator(const CXXNewExpr *NE, SVal Target, CheckerContext &C) const { - if (!C.wasInlined) - processNewAllocation(NE, C, Target); + if (!C.wasInlined) { + processNewAllocation(NE, C, Target, + (NE->isArray() ? AF_CXXNewArray : AF_CXXNew)); + } } // Sets the extent value of the MemRegion allocated by @@ -1424,14 +1370,14 @@ void MallocChecker::checkPreStmt(const CXXDeleteExpr *DE, if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol()) checkUseAfterFree(Sym, C, DE->getArgument()); - if (!MemFunctionInfo.isStandardNewDelete(DE->getOperatorDelete(), - C.getASTContext())) + if (!isStandardNewDelete(DE->getOperatorDelete())) return; ProgramStateRef State = C.getState(); bool IsKnownToBeAllocated; State = FreeMemAux(C, DE->getArgument(), DE, State, - /*Hold*/ false, IsKnownToBeAllocated); + /*Hold*/ false, IsKnownToBeAllocated, + (DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew)); C.addTransition(State); } @@ -1477,7 +1423,7 @@ void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call, bool IsKnownToBeAllocatedMemory; ProgramStateRef State = FreeMemAux(C, Call.getArgExpr(0), Call.getOriginExpr(), C.getState(), - /*Hold=*/true, IsKnownToBeAllocatedMemory, + /*Hold=*/true, IsKnownToBeAllocatedMemory, AF_Malloc, /*RetNullOnFailure=*/true); C.addTransition(State); @@ -1490,15 +1436,16 @@ MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, if (!State) return nullptr; - if (Att->getModule() != MemFunctionInfo.II_malloc) + if (Att->getModule()->getName() != + MemFunctionInfo.CD_malloc.getFunctionName()) return nullptr; OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); if (I != E) { return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()), UndefinedVal(), - State); + State, AF_Malloc); } - return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State); + return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State, AF_Malloc); } ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, @@ -1513,10 +1460,9 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, } ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, - const CallExpr *CE, - SVal Size, SVal Init, - ProgramStateRef State, - AllocationFamily Family) { + const CallExpr *CE, SVal Size, + SVal Init, ProgramStateRef State, + AllocationFamily Family) { if (!State) return nullptr; @@ -1587,15 +1533,17 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, if (!State) return nullptr; - if (Att->getModule() != MemFunctionInfo.II_malloc) + if (Att->getModule()->getName() != + MemFunctionInfo.CD_malloc.getFunctionName()) return nullptr; bool IsKnownToBeAllocated = false; for (const auto &Arg : Att->args()) { - ProgramStateRef StateI = FreeMemAux( - C, CE, State, Arg.getASTIndex(), - Att->getOwnKind() == OwnershipAttr::Holds, IsKnownToBeAllocated); + ProgramStateRef StateI = + FreeMemAux(C, CE, State, Arg.getASTIndex(), + Att->getOwnKind() == OwnershipAttr::Holds, + IsKnownToBeAllocated, AF_Malloc); if (StateI) State = StateI; } @@ -1605,6 +1553,7 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, ProgramStateRef State, unsigned Num, bool Hold, bool &IsKnownToBeAllocated, + AllocationFamily Family, bool ReturnsNullOnFailure) const { if (!State) return nullptr; @@ -1613,7 +1562,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, return nullptr; return FreeMemAux(C, CE->getArg(Num), CE, State, Hold, IsKnownToBeAllocated, - ReturnsNullOnFailure); + Family, ReturnsNullOnFailure); } /// Checks if the previous call to free on the given symbol failed - if free @@ -1631,58 +1580,7 @@ static bool didPreviousFreeFail(ProgramStateRef State, return false; } -static AllocationFamily -getAllocationFamily(const MemFunctionInfoTy &MemFunctionInfo, CheckerContext &C, - const Stmt *S) { - - if (!S) - return AF_None; - - if (const CallExpr *CE = dyn_cast(S)) { - const FunctionDecl *FD = C.getCalleeDecl(CE); - - if (!FD) - FD = dyn_cast(CE->getCalleeDecl()); - - ASTContext &Ctx = C.getASTContext(); - - if (MemFunctionInfo.isCMemFunction(FD, Ctx, AF_Malloc, - MemoryOperationKind::MOK_Any)) - return AF_Malloc; - - if (MemFunctionInfo.isStandardNewDelete(FD, Ctx)) { - OverloadedOperatorKind Kind = FD->getOverloadedOperator(); - if (Kind == OO_New || Kind == OO_Delete) - return AF_CXXNew; - else if (Kind == OO_Array_New || Kind == OO_Array_Delete) - return AF_CXXNewArray; - } - - if (MemFunctionInfo.isCMemFunction(FD, Ctx, AF_IfNameIndex, - MemoryOperationKind::MOK_Any)) - return AF_IfNameIndex; - - if (MemFunctionInfo.isCMemFunction(FD, Ctx, AF_Alloca, - MemoryOperationKind::MOK_Any)) - return AF_Alloca; - - return AF_None; - } - - if (const CXXNewExpr *NE = dyn_cast(S)) - return NE->isArray() ? AF_CXXNewArray : AF_CXXNew; - - if (const CXXDeleteExpr *DE = dyn_cast(S)) - return DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew; - - if (isa(S)) - return AF_Malloc; - - return AF_None; -} - -static bool printAllocDeallocName(raw_ostream &os, CheckerContext &C, - const Expr *E) { +static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E) { if (const CallExpr *CE = dyn_cast(E)) { // FIXME: This doesn't handle indirect calls. const FunctionDecl *FD = CE->getDirectCallee(); @@ -1721,10 +1619,7 @@ static bool printAllocDeallocName(raw_ostream &os, CheckerContext &C, return false; } -static void printExpectedAllocName(raw_ostream &os, - const MemFunctionInfoTy &MemFunctionInfo, - CheckerContext &C, const Expr *E) { - AllocationFamily Family = getAllocationFamily(MemFunctionInfo, C, E); +static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family) { switch(Family) { case AF_Malloc: os << "malloc()"; return; @@ -1749,12 +1644,10 @@ static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) { } } -ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, - const Expr *ArgExpr, - const Expr *ParentExpr, - ProgramStateRef State, bool Hold, - bool &IsKnownToBeAllocated, - bool ReturnsNullOnFailure) const { +ProgramStateRef MallocChecker::FreeMemAux( + CheckerContext &C, const Expr *ArgExpr, const Expr *ParentExpr, + ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated, + AllocationFamily Family, bool ReturnsNullOnFailure) const { if (!State) return nullptr; @@ -1784,7 +1677,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, // Nonlocs can't be freed, of course. // Non-region locations (labels and fixed addresses) also shouldn't be freed. if (!R) { - ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); + ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, Family); return nullptr; } @@ -1792,7 +1685,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, // Blocks might show up as heap data, but should not be free()d if (isa(R)) { - ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); + ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, Family); return nullptr; } @@ -1812,7 +1705,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, if (isa(R)) ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange()); else - ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); + ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, Family); return nullptr; } @@ -1851,9 +1744,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, RsBase->isEscaped()) { // Check if an expected deallocation function matches the real one. - bool DeallocMatchesAlloc = - RsBase->getAllocationFamily() == - getAllocationFamily(MemFunctionInfo, C, ParentExpr); + bool DeallocMatchesAlloc = RsBase->getAllocationFamily() == Family; if (!DeallocMatchesAlloc) { ReportMismatchedDealloc(C, ArgExpr->getSourceRange(), ParentExpr, RsBase, SymBase, Hold); @@ -1868,14 +1759,15 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, Offset.getOffset() != 0) { const Expr *AllocExpr = cast(RsBase->getStmt()); ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, - AllocExpr); + Family, AllocExpr); return nullptr; } } } if (SymBase->getType()->isFunctionPointerType()) { - ReportFunctionPointerFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); + ReportFunctionPointerFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, + Family); return nullptr; } @@ -1893,9 +1785,12 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, } } - AllocationFamily Family = - RsBase ? RsBase->getAllocationFamily() - : getAllocationFamily(MemFunctionInfo, C, ParentExpr); + // If we don't know anything about this symbol, a free on it may be totally + // valid. If this is the case, lets assume that the allocation family of the + // freeing function is the same as the symbols allocation family, and go with + // that. + assert(!RsBase || (RsBase && RsBase->getAllocationFamily() == Family)); + // Normal free. if (Hold) return State->set(SymBase, @@ -1941,14 +1836,6 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family, llvm_unreachable("unhandled family"); } -Optional -MallocChecker::getCheckIfTracked(CheckerContext &C, - const Stmt *AllocDeallocStmt, - bool IsALeakCheck) const { - return getCheckIfTracked( - getAllocationFamily(MemFunctionInfo, C, AllocDeallocStmt), IsALeakCheck); -} - Optional MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym, bool IsALeakCheck) const { @@ -2048,15 +1935,14 @@ bool MallocChecker::SummarizeRegion(raw_ostream &os, } void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, - SourceRange Range, - const Expr *DeallocExpr) const { + SourceRange Range, const Expr *DeallocExpr, + AllocationFamily Family) const { if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) return; - Optional CheckKind = - getCheckIfTracked(C, DeallocExpr); + Optional CheckKind = getCheckIfTracked(Family); if (!CheckKind.hasValue()) return; @@ -2073,7 +1959,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, MR = ER->getSuperRegion(); os << "Argument to "; - if (!printAllocDeallocName(os, C, DeallocExpr)) + if (!printMemFnName(os, C, DeallocExpr)) os << "deallocator"; os << " is "; @@ -2084,7 +1970,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, else os << "not memory allocated by "; - printExpectedAllocName(os, MemFunctionInfo, C, DeallocExpr); + printExpectedAllocName(os, Family); auto R = std::make_unique(*BT_BadFree[*CheckKind], os.str(), N); @@ -2146,25 +2032,25 @@ void MallocChecker::ReportMismatchedDealloc(CheckerContext &C, llvm::raw_svector_ostream DeallocOs(DeallocBuf); if (OwnershipTransferred) { - if (printAllocDeallocName(DeallocOs, C, DeallocExpr)) + if (printMemFnName(DeallocOs, C, DeallocExpr)) os << DeallocOs.str() << " cannot"; else os << "Cannot"; os << " take ownership of memory"; - if (printAllocDeallocName(AllocOs, C, AllocExpr)) + if (printMemFnName(AllocOs, C, AllocExpr)) os << " allocated by " << AllocOs.str(); } else { os << "Memory"; - if (printAllocDeallocName(AllocOs, C, AllocExpr)) + if (printMemFnName(AllocOs, C, AllocExpr)) os << " allocated by " << AllocOs.str(); os << " should be deallocated by "; printExpectedDeallocName(os, RS->getAllocationFamily()); - if (printAllocDeallocName(DeallocOs, C, DeallocExpr)) - os << ", not " << DeallocOs.str(); + if (printMemFnName(DeallocOs, C, DeallocExpr)) + os << ", not " << DeallocOs.str(); } auto R = std::make_unique(*BT_MismatchedDealloc, @@ -2178,15 +2064,14 @@ void MallocChecker::ReportMismatchedDealloc(CheckerContext &C, void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range, const Expr *DeallocExpr, + AllocationFamily Family, const Expr *AllocExpr) const { - if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) return; - Optional CheckKind = - getCheckIfTracked(C, AllocExpr); + Optional CheckKind = getCheckIfTracked(Family); if (!CheckKind.hasValue()) return; @@ -2215,14 +2100,14 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal, int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth(); os << "Argument to "; - if (!printAllocDeallocName(os, C, DeallocExpr)) + if (!printMemFnName(os, C, DeallocExpr)) os << "deallocator"; os << " is offset by " << offsetBytes << " " << ((abs(offsetBytes) > 1) ? "bytes" : "byte") << " from the start of "; - if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr)) + if (AllocExpr && printMemFnName(AllocNameOs, C, AllocExpr)) os << "memory allocated by " << AllocNameOs.str(); else os << "allocated memory"; @@ -2360,11 +2245,12 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C, void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, SourceRange Range, - const Expr *FreeExpr) const { + const Expr *FreeExpr, + AllocationFamily Family) const { if (!ChecksEnabled[CK_MallocChecker]) return; - Optional CheckKind = getCheckIfTracked(C, FreeExpr); + Optional CheckKind = getCheckIfTracked(Family); if (!CheckKind.hasValue()) return; @@ -2381,7 +2267,7 @@ void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, MR = ER->getSuperRegion(); Os << "Argument to "; - if (!printAllocDeallocName(Os, C, FreeExpr)) + if (!printMemFnName(Os, C, FreeExpr)) Os << "deallocator"; Os << " is a function pointer"; @@ -2394,11 +2280,10 @@ void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal, } } -ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C, - const CallExpr *CE, - bool ShouldFreeOnFail, - ProgramStateRef State, - bool SuffixWithN) const { +ProgramStateRef +MallocChecker::ReallocMemAux(CheckerContext &C, const CallExpr *CE, + bool ShouldFreeOnFail, ProgramStateRef State, + AllocationFamily Family, bool SuffixWithN) const { if (!State) return nullptr; @@ -2445,8 +2330,8 @@ ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C, // If the ptr is NULL and the size is not 0, the call is equivalent to // malloc(size). if (PrtIsNull && !SizeIsZero) { - ProgramStateRef stateMalloc = MallocMemAux(C, CE, TotalSize, - UndefinedVal(), StatePtrIsNull); + ProgramStateRef stateMalloc = + MallocMemAux(C, CE, TotalSize, UndefinedVal(), StatePtrIsNull, Family); return stateMalloc; } @@ -2469,16 +2354,16 @@ ProgramStateRef MallocChecker::ReallocMemAux(CheckerContext &C, // If size was equal to 0, either NULL or a pointer suitable to be passed // to free() is returned. We just free the input pointer and do not add // any constrains on the output pointer. - if (ProgramStateRef stateFree = - FreeMemAux(C, CE, StateSizeIsZero, 0, false, IsKnownToBeAllocated)) + if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0, false, + IsKnownToBeAllocated, Family)) return stateFree; // Default behavior. if (ProgramStateRef stateFree = - FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocated)) { + FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocated, Family)) { - ProgramStateRef stateRealloc = MallocMemAux(C, CE, TotalSize, - UnknownVal(), stateFree); + ProgramStateRef stateRealloc = + MallocMemAux(C, CE, TotalSize, UnknownVal(), stateFree, Family); if (!stateRealloc) return nullptr; @@ -2511,7 +2396,7 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE, SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1)); - return MallocMemAux(C, CE, TotalSize, zeroVal, State); + return MallocMemAux(C, CE, TotalSize, zeroVal, State, AF_Malloc); } MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N, @@ -2694,12 +2579,8 @@ void MallocChecker::checkPreCall(const CallEvent &Call, if (!FD) return; - ASTContext &Ctx = C.getASTContext(); if (ChecksEnabled[CK_MallocChecker] && - (MemFunctionInfo.isCMemFunction(FD, Ctx, AF_Malloc, - MemoryOperationKind::MOK_Free) || - MemFunctionInfo.isCMemFunction(FD, Ctx, AF_IfNameIndex, - MemoryOperationKind::MOK_Free))) + (MemFunctionInfo.isCMemFreeFunction(Call))) return; } @@ -2996,11 +2877,9 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( if (!FD) return true; - ASTContext &ASTC = State->getStateManager().getContext(); - // If it's one of the allocation functions we can reason about, we model // its behavior explicitly. - if (MemFunctionInfo.isMemFunction(FD, ASTC)) + if (MemFunctionInfo.isMemFunction(*Call)) return false; // If it's not a system call, assume it frees memory. diff --git a/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp index 6724eead50720..077a34810db77 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp @@ -98,12 +98,13 @@ bool VforkChecker::isCallWhitelisted(const IdentifierInfo *II, if (VforkWhitelist.empty()) { // According to manpage. const char *ids[] = { - "_exit", "_Exit", + "_exit", "execl", - "execlp", "execle", + "execlp", "execv", + "execve", "execvp", "execvpe", nullptr diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp new file mode 100644 index 0000000000000..6e276a5d69775 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/cert/PutenvWithAutoChecker.cpp @@ -0,0 +1,64 @@ +//== PutenvWithAutoChecker.cpp --------------------------------- -*- C++ -*--=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines PutenvWithAutoChecker which finds calls of ``putenv`` +// function with automatic variable as the argument. +// https://wiki.sei.cmu.edu/confluence/x/6NYxBQ +// +//===----------------------------------------------------------------------===// + +#include "../AllocationState.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" + +using namespace clang; +using namespace ento; + +class PutenvWithAutoChecker : public Checker { +private: + BugType BT{this, "'putenv' function should not be called with auto variables", + categories::SecurityError}; + const CallDescription Putenv{"putenv", 1}; + +public: + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; +}; + +void PutenvWithAutoChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { + if (!Call.isCalled(Putenv)) + return; + + SVal ArgV = Call.getArgSVal(0); + const Expr *ArgExpr = Call.getArgExpr(0); + const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace(); + + if (!isa(MSR)) + return; + + StringRef ErrorMsg = "The 'putenv' function should not be called with " + "arguments that have automatic storage"; + ExplodedNode *N = C.generateErrorNode(); + auto Report = std::make_unique(BT, ErrorMsg, N); + + // Track the argument. + bugreporter::trackExpressionValue(Report->getErrorNode(), ArgExpr, *Report); + + C.emitReport(std::move(Report)); +} + +void ento::registerPutenvWithAuto(CheckerManager &Mgr) { + Mgr.registerChecker(); +} + +bool ento::shouldRegisterPutenvWithAuto(const LangOptions &) { return true; } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 168d6fe6ec48f..4fc23d8ac9417 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -889,24 +889,22 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx, Params); } -SVal CXXConstructorCall::getCXXThisVal() const { +SVal AnyCXXConstructorCall::getCXXThisVal() const { if (Data) return loc::MemRegionVal(static_cast(Data)); return UnknownVal(); } -void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values, +void AnyCXXConstructorCall::getExtraInvalidatedValues(ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const { - if (Data) { - loc::MemRegionVal MV(static_cast(Data)); - if (SymbolRef Sym = MV.getAsSymbol(true)) - ETraits->setTrait(Sym, - RegionAndSymbolInvalidationTraits::TK_SuppressEscape); - Values.push_back(MV); - } + SVal V = getCXXThisVal(); + if (SymbolRef Sym = V.getAsSymbol(true)) + ETraits->setTrait(Sym, + RegionAndSymbolInvalidationTraits::TK_SuppressEscape); + Values.push_back(V); } -void CXXConstructorCall::getInitialStackFrameContents( +void AnyCXXConstructorCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); @@ -920,6 +918,14 @@ void CXXConstructorCall::getInitialStackFrameContents( } } +const StackFrameContext * +CXXInheritedConstructorCall::getInheritingStackFrame() const { + const StackFrameContext *SFC = getLocationContext()->getStackFrame(); + while (isa(SFC->getCallSite())) + SFC = SFC->getParent()->getStackFrame(); + return SFC; +} + SVal CXXDestructorCall::getCXXThisVal() const { if (Data) return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer()); @@ -1392,17 +1398,20 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx, if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx)) return Out; - // All other cases are handled by getCall. - assert(isa(CallSite) && - "This is not an inlineable statement"); - SValBuilder &SVB = State->getStateManager().getSValBuilder(); const auto *Ctor = cast(CalleeCtx->getDecl()); Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx); SVal ThisVal = State->getSVal(ThisPtr); - return getCXXConstructorCall(cast(CallSite), - ThisVal.getAsRegion(), State, CallerCtx); + if (const auto *CE = dyn_cast(CallSite)) + return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerCtx); + else if (const auto *CIE = dyn_cast(CallSite)) + return getCXXInheritedConstructorCall(CIE, ThisVal.getAsRegion(), State, + CallerCtx); + else { + // All other cases are handled by getCall. + llvm_unreachable("This is not an inlineable statement"); + } } // Fall back to the CFG. The only thing we haven't handled yet is diff --git a/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp b/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp index bdae3e605efff..a601370775b45 100644 --- a/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp +++ b/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp @@ -9,13 +9,18 @@ #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" // Common strings used for the "category" of many static analyzer issues. -namespace clang { namespace ento { namespace categories { +namespace clang { +namespace ento { +namespace categories { -const char * const CoreFoundationObjectiveC = "Core Foundation/Objective-C"; -const char * const LogicError = "Logic error"; -const char * const MemoryRefCount = - "Memory (Core Foundation/Objective-C/OSObject)"; -const char * const MemoryError = "Memory error"; -const char * const UnixAPI = "Unix API"; -const char * const CXXObjectLifecycle = "C++ object lifecycle"; -}}} +const char *const CoreFoundationObjectiveC = "Core Foundation/Objective-C"; +const char *const LogicError = "Logic error"; +const char *const MemoryRefCount = + "Memory (Core Foundation/Objective-C/OSObject)"; +const char *const MemoryError = "Memory error"; +const char *const UnixAPI = "Unix API"; +const char *const CXXObjectLifecycle = "C++ object lifecycle"; +const char *const SecurityError = "Security error"; +} // namespace categories +} // namespace ento +} // namespace clang diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index eb32a3276550b..801b30a9ab6c6 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1212,7 +1212,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // C++, OpenMP and ARC stuff we don't support yet. case Expr::ObjCIndirectCopyRestoreExprClass: case Stmt::CXXDependentScopeMemberExprClass: - case Stmt::CXXInheritedCtorInitExprClass: case Stmt::CXXTryStmtClass: case Stmt::CXXTypeidExprClass: case Stmt::CXXUuidofExprClass: @@ -1618,6 +1617,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); break; + case Stmt::CXXInheritedCtorInitExprClass: + Bldr.takeNodes(Pred); + VisitCXXInheritedCtorInitExpr(cast(S), Pred, + Dst); + Bldr.addNodes(Dst); + break; + case Stmt::CXXNewExprClass: { Bldr.takeNodes(Pred); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index b816aab7c18f8..d05b31a64427e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -109,7 +109,7 @@ SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue, return LValue; } -std::pair ExprEngine::prepareForObjectConstruction( +std::pair ExprEngine::handleConstructionContext( const Expr *E, ProgramStateRef State, const LocationContext *LCtx, const ConstructionContext *CC, EvalCallOptions &CallOpts) { SValBuilder &SVB = getSValBuilder(); @@ -202,7 +202,7 @@ std::pair ExprEngine::prepareForObjectConstruction( CallerLCtx = CallerLCtx->getParent(); assert(!isa(CallerLCtx)); } - return prepareForObjectConstruction( + return handleConstructionContext( cast(SFC->getCallSite()), State, CallerLCtx, RTC->getConstructionContext(), CallOpts); } else { @@ -247,7 +247,7 @@ std::pair ExprEngine::prepareForObjectConstruction( ProgramStateRef PreElideState = State; EvalCallOptions PreElideCallOpts = CallOpts; - std::tie(State, V) = prepareForObjectConstruction( + std::tie(State, V) = handleConstructionContext( CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts); // FIXME: This definition of "copy elision has not failed" is unreliable. @@ -392,26 +392,32 @@ std::pair ExprEngine::prepareForObjectConstruction( State, loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx))); } -void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, - ExplodedNode *Pred, - ExplodedNodeSet &destNodes) { +void ExprEngine::handleConstructor(const Expr *E, + ExplodedNode *Pred, + ExplodedNodeSet &destNodes) { + const auto *CE = dyn_cast(E); + const auto *CIE = dyn_cast(E); + assert(CE || CIE); + const LocationContext *LCtx = Pred->getLocationContext(); ProgramStateRef State = Pred->getState(); SVal Target = UnknownVal(); - if (Optional ElidedTarget = - getObjectUnderConstruction(State, CE, LCtx)) { - // We've previously modeled an elidable constructor by pretending that it in - // fact constructs into the correct target. This constructor can therefore - // be skipped. - Target = *ElidedTarget; - StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); - State = finishObjectConstruction(State, CE, LCtx); - if (auto L = Target.getAs()) - State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); - Bldr.generateNode(CE, Pred, State); - return; + if (CE) { + if (Optional ElidedTarget = + getObjectUnderConstruction(State, CE, LCtx)) { + // We've previously modeled an elidable constructor by pretending that it + // in fact constructs into the correct target. This constructor can + // therefore be skipped. + Target = *ElidedTarget; + StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); + State = finishObjectConstruction(State, CE, LCtx); + if (auto L = Target.getAs()) + State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); + Bldr.generateNode(CE, Pred, State); + return; + } } // FIXME: Handle arrays, which run the same constructor for every element. @@ -423,10 +429,16 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, assert(C || getCurrentCFGElement().getAs()); const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr; - switch (CE->getConstructionKind()) { + const CXXConstructExpr::ConstructionKind CK = + CE ? CE->getConstructionKind() : CIE->getConstructionKind(); + switch (CK) { case CXXConstructExpr::CK_Complete: { + // Inherited constructors are always base class constructors. + assert(CE && !CIE && "A complete constructor is inherited?!"); + + // The target region is found from construction context. std::tie(State, Target) = - prepareForObjectConstruction(CE, State, LCtx, CC, CallOpts); + handleConstructionContext(CE, State, LCtx, CC, CallOpts); break; } case CXXConstructExpr::CK_VirtualBase: { @@ -455,9 +467,9 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, // FIXME: Instead of relying on the ParentMap, we should have the // trigger-statement (InitListExpr in this case) passed down from CFG or // otherwise always available during construction. - if (dyn_cast_or_null(LCtx->getParentMap().getParent(CE))) { + if (dyn_cast_or_null(LCtx->getParentMap().getParent(E))) { MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); - Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(CE, LCtx)); + Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; break; } @@ -468,14 +480,13 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, LCtx->getStackFrame()); SVal ThisVal = State->getSVal(ThisPtr); - if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { + if (CK == CXXConstructExpr::CK_Delegating) { Target = ThisVal; } else { // Cast to the base type. - bool IsVirtual = - (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); - SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), - IsVirtual); + bool IsVirtual = (CK == CXXConstructExpr::CK_VirtualBase); + SVal BaseVal = + getStoreManager().evalDerivedToBase(ThisVal, E->getType(), IsVirtual); Target = BaseVal; } break; @@ -487,23 +498,27 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, "Prepare for object construction"); ExplodedNodeSet DstPrepare; StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx); - BldrPrepare.generateNode(CE, Pred, State, &T, ProgramPoint::PreStmtKind); + BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind); assert(DstPrepare.size() <= 1); if (DstPrepare.size() == 0) return; Pred = *BldrPrepare.begin(); } + const MemRegion *TargetRegion = Target.getAsRegion(); CallEventManager &CEMgr = getStateManager().getCallEventManager(); - CallEventRef Call = - CEMgr.getCXXConstructorCall(CE, Target.getAsRegion(), State, LCtx); + CallEventRef<> Call = + CIE ? (CallEventRef<>)CEMgr.getCXXInheritedConstructorCall( + CIE, TargetRegion, State, LCtx) + : (CallEventRef<>)CEMgr.getCXXConstructorCall( + CE, TargetRegion, State, LCtx); ExplodedNodeSet DstPreVisit; - getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); + getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, E, *this); - // FIXME: Is it possible and/or useful to do this before PreStmt? ExplodedNodeSet PreInitialized; - { + if (CE) { + // FIXME: Is it possible and/or useful to do this before PreStmt? StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); for (ExplodedNodeSet::iterator I = DstPreVisit.begin(), E = DstPreVisit.end(); @@ -528,6 +543,8 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, Bldr.generateNode(CE, *I, State, /*tag=*/nullptr, ProgramPoint::PreStmtKind); } + } else { + PreInitialized = DstPreVisit; } ExplodedNodeSet DstPreCall; @@ -537,7 +554,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, ExplodedNodeSet DstEvaluated; StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); - if (CE->getConstructor()->isTrivial() && + if (CE && CE->getConstructor()->isTrivial() && CE->getConstructor()->isCopyOrMoveConstructor() && !CallOpts.IsArrayCtorOrDtor) { // FIXME: Handle other kinds of trivial constructors as well. @@ -560,9 +577,9 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, // paths when no-return temporary destructors are used for assertions. const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext(); if (!ADC->getCFGBuildOptions().AddTemporaryDtors) { - const MemRegion *Target = Call->getCXXThisVal().getAsRegion(); - if (Target && isa(Target) && - Call->getDecl()->getParent()->isAnyDestructorNoReturn()) { + if (TargetRegion && isa(TargetRegion) && + cast(Call->getDecl()) + ->getParent()->isAnyDestructorNoReturn()) { // If we've inlined the constructor, then DstEvaluated would be empty. // In this case we still want a sink, which could be implemented @@ -575,7 +592,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, "We should not have inlined this constructor!"); for (ExplodedNode *N : DstEvaluated) { - Bldr.generateSink(CE, N, N->getState()); + Bldr.generateSink(E, N, N->getState()); } // There is no need to run the PostCall and PostStmt checker @@ -595,7 +612,19 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, getCheckerManager().runCheckersForPostCall(DstPostCall, DstPostArgumentCleanup, *Call, *this); - getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); + getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this); +} + +void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, + ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + handleConstructor(CE, Pred, Dst); +} + +void ExprEngine::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + handleConstructor(CE, Pred, Dst); } void ExprEngine::VisitCXXDestructor(QualType ObjectType, diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 01a371e664b2e..781cc9f7943db 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -668,8 +668,8 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, assert(RTC->getStmt() == Call.getOriginExpr()); EvalCallOptions CallOpts; // FIXME: We won't really need those. std::tie(State, Target) = - prepareForObjectConstruction(Call.getOriginExpr(), State, LCtx, - RTC->getConstructionContext(), CallOpts); + handleConstructionContext(Call.getOriginExpr(), State, LCtx, + RTC->getConstructionContext(), CallOpts); const MemRegion *TargetR = Target.getAsRegion(); assert(TargetR); // Invalidate the region so that it didn't look uninitialized. If this is @@ -789,6 +789,11 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, break; } + case CE_CXXInheritedConstructor: { + // This doesn't really increase the cost of inlining ever, because + // the stack frame of the inherited constructor is trivial. + return CIP_Allowed; + } case CE_CXXDestructor: { if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors)) return CIP_DisallowedAlways; diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index 8eaaa08dc44ba..e655aae45832d 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -542,6 +542,11 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ if (!Loc) return true; + // Anonymous parameters of an inheriting constructor are live for the entire + // duration of the constructor. + if (isa(Loc)) + return true; + if (LCtx->getAnalysis()->isLive(Loc, VR->getDecl())) return true; diff --git a/clang/lib/Tooling/ArgumentsAdjusters.cpp b/clang/lib/Tooling/ArgumentsAdjusters.cpp index a609e4ed2469b..5869377a03c93 100644 --- a/clang/lib/Tooling/ArgumentsAdjusters.cpp +++ b/clang/lib/Tooling/ArgumentsAdjusters.cpp @@ -26,7 +26,7 @@ ArgumentsAdjuster getClangSyntaxOnlyAdjuster() { return [](const CommandLineArguments &Args, StringRef /*unused*/) { CommandLineArguments AdjustedArgs; bool HasSyntaxOnly = false; - const std::vector OutputCommands = { + constexpr llvm::StringRef OutputCommands[] = { // FIXME: Add other options that generate output. "-save-temps", "--save-temps", diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp index a17b880a71a01..43dc32e158d3e 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp @@ -126,12 +126,14 @@ class AdditionalUSRFinder : public RecursiveASTVisitor { addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl()); } - void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) { - RecordDecl = RecordDecl->getDefinition(); + void addUSRsOfCtorDtors(const CXXRecordDecl *RD) { + const auto* RecordDecl = RD->getDefinition(); // Skip if the CXXRecordDecl doesn't have definition. - if (!RecordDecl) + if (!RecordDecl) { + USRSet.insert(getUSRForDecl(RD)); return; + } for (const auto *CtorDecl : RecordDecl->ctors()) USRSet.insert(getUSRForDecl(CtorDecl)); diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index be200f2e3560e..bee20ebb878dd 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -619,7 +619,8 @@ buildASTFromCode(StringRef Code, StringRef FileName, std::unique_ptr buildASTFromCodeWithArgs( StringRef Code, const std::vector &Args, StringRef FileName, StringRef ToolName, std::shared_ptr PCHContainerOps, - ArgumentsAdjuster Adjuster, const FileContentMappings &VirtualMappedFiles) { + ArgumentsAdjuster Adjuster, const FileContentMappings &VirtualMappedFiles, + DiagnosticConsumer *DiagConsumer) { std::vector> ASTs; ASTBuilderAction Action(ASTs); llvm::IntrusiveRefCntPtr OverlayFileSystem( @@ -633,6 +634,7 @@ std::unique_ptr buildASTFromCodeWithArgs( ToolInvocation Invocation( getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName), &Action, Files.get(), std::move(PCHContainerOps)); + Invocation.setDiagnosticConsumer(DiagConsumer); InMemoryFileSystem->addFile(FileName, 0, llvm::MemoryBuffer::getMemBufferCopy(Code)); diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h index 8542387d4277a..afbaeddd88a87 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator.h +++ b/clang/test/Analysis/Inputs/system-header-simulator.h @@ -98,6 +98,12 @@ typedef int pid_t; pid_t fork(void); pid_t vfork(void); int execl(const char *path, const char *arg, ...); +int execle(const char *path, const char *arg, ...); +int execlp(const char *file, const char *arg, ...); +int execv(const char *path, char *const argv[]); +int execve(const char *path, char *const argv[], char *const envp[]); +int execvp(const char *file, char *const argv[]); +int execvpe(const char *file, char *const argv[], char *const envp[]); void exit(int status) __attribute__ ((__noreturn__)); void _exit(int status) __attribute__ ((__noreturn__)); diff --git a/clang/test/Analysis/cert/pos34-c-fp-suppression.cpp b/clang/test/Analysis/cert/pos34-c-fp-suppression.cpp new file mode 100644 index 0000000000000..d982fcb8a1baf --- /dev/null +++ b/clang/test/Analysis/cert/pos34-c-fp-suppression.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=alpha.security.cert.pos.34c\ +// RUN: -verify %s + +#include "../Inputs/system-header-simulator.h" +void free(void *memblock); +void *malloc(size_t size); +int putenv(char *); +int rand(); + +namespace test_auto_var_used_good { + +extern char *ex; +int test_extern() { + return putenv(ex); // no-warning: extern storage class. +} + +void foo(void) { + char *buffer = (char *)"huttah!"; + if (rand() % 2 == 0) { + buffer = (char *)malloc(5); + strcpy(buffer, "woot"); + } + putenv(buffer); +} + +void bar(void) { + char *buffer = (char *)malloc(5); + strcpy(buffer, "woot"); + + if (rand() % 2 == 0) { + free(buffer); + buffer = (char *)"blah blah blah"; + } + putenv(buffer); +} + +void baz() { + char env[] = "NAME=value"; + // TODO: False Positive + putenv(env); + // expected-warning@-1 {{The 'putenv' function should not be called with arguments that have automatic storage}} + + /* + DO SOMETHING + */ + + putenv((char *)"NAME=anothervalue"); +} + +} // namespace test_auto_var_used_good diff --git a/clang/test/Analysis/cert/pos34-c.cpp b/clang/test/Analysis/cert/pos34-c.cpp new file mode 100644 index 0000000000000..f2bd7b393d889 --- /dev/null +++ b/clang/test/Analysis/cert/pos34-c.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=alpha.security.cert.pos.34c\ +// RUN: -verify %s + +// Examples from the CERT rule's page. +// https://wiki.sei.cmu.edu/confluence/x/6NYxBQ + +#include "../Inputs/system-header-simulator.h" +void free(void *memblock); +void *malloc(size_t size); +int putenv(char *); +int snprintf(char *str, size_t size, const char *format, ...); + +namespace test_auto_var_used_bad { + +int volatile_memory1(const char *var) { + char env[1024]; + int retval = snprintf(env, sizeof(env), "TEST=%s", var); + if (retval < 0 || (size_t)retval >= sizeof(env)) { + /* Handle error */ + } + + return putenv(env); + // expected-warning@-1 {{The 'putenv' function should not be called with arguments that have automatic storage}} +} + +} // namespace test_auto_var_used_bad + +namespace test_auto_var_used_good { + +int test_static(const char *var) { + static char env[1024]; + + int retval = snprintf(env, sizeof(env), "TEST=%s", var); + if (retval < 0 || (size_t)retval >= sizeof(env)) { + /* Handle error */ + } + + return putenv(env); +} + +int test_heap_memory(const char *var) { + static char *oldenv; + const char *env_format = "TEST=%s"; + const size_t len = strlen(var) + strlen(env_format); + char *env = (char *)malloc(len); + if (env == NULL) { + return -1; + } + if (putenv(env) != 0) { // no-warning: env was dynamically allocated. + free(env); + return -1; + } + if (oldenv != NULL) { + free(oldenv); /* avoid memory leak */ + } + oldenv = env; + return 0; +} + +} // namespace test_auto_var_used_good diff --git a/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp b/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp new file mode 100644 index 0000000000000..ff82c129bc700 --- /dev/null +++ b/clang/test/Analysis/cxx-inherited-ctor-init-expr.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_eval(bool); + +namespace basic_tests { +struct A { + int x; + A(int x): x(x) {} +}; + +struct B : A { + using A::A; +}; + +struct C : B { + using B::B; +}; + +void test_B() { + B b(1); + clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}} +} + +void test_C() { + C c(2); + clang_analyzer_eval(c.x == 2); // expected-warning{{TRUE}} +} +} // namespace basic_tests + +namespace arguments_with_constructors { +struct S { + int x, y; + S(int x, int y): x(x), y(y) {} + ~S() {} +}; + +struct A { + S s; + int z; + A(S s, int z) : s(s), z(z) {} +}; + +struct B : A { + using A::A; +}; + +void test_B() { + B b(S(1, 2), 3); + // FIXME: There should be no execution path on which this is false. + clang_analyzer_eval(b.s.x == 1); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} + + // FIXME: There should be no execution path on which this is false. + clang_analyzer_eval(b.s.y == 2); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} + + clang_analyzer_eval(b.z == 3); // expected-warning{{TRUE}} +} +} // namespace arguments_with_constructors diff --git a/clang/test/Analysis/iterator-modelling.cpp b/clang/test/Analysis/iterator-modelling.cpp index b2551939986a0..4e40319cedc1f 100644 --- a/clang/test/Analysis/iterator-modelling.cpp +++ b/clang/test/Analysis/iterator-modelling.cpp @@ -100,6 +100,16 @@ void plus_equal(const std::vector &v) { clang_analyzer_express(clang_analyzer_iterator_position(i)); //expected-warning{{$v.begin() + 2}} } +void plus_equal_negative(const std::vector &v) { + auto i = v.end(); + + clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); + + i += -2; + + clang_analyzer_express(clang_analyzer_iterator_position(i)); //expected-warning{{$v.end() - 2}} +} + void minus_equal(const std::vector &v) { auto i = v.end(); @@ -110,6 +120,16 @@ void minus_equal(const std::vector &v) { clang_analyzer_express(clang_analyzer_iterator_position(i)); //expected-warning{{$v.end() - 2}} } +void minus_equal_negative(const std::vector &v) { + auto i = v.begin(); + + clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); + + i -= -2; + + clang_analyzer_express(clang_analyzer_iterator_position(i)); //expected-warning{{$v.begin() + 2}} +} + void copy(const std::vector &v) { auto i1 = v.end(); @@ -132,6 +152,17 @@ void plus(const std::vector &v) { clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$v.begin() + 2}} } +void plus_negative(const std::vector &v) { + auto i1 = v.end(); + + clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); + + auto i2 = i1 + (-2); + + clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$v.end() - 2}} +} + void minus(const std::vector &v) { auto i1 = v.end(); @@ -143,6 +174,17 @@ void minus(const std::vector &v) { clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$v.end() - 2}} } +void minus_negative(const std::vector &v) { + auto i1 = v.begin(); + + clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); + + auto i2 = i1 - (-2); + + clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$v.begin() + 2}} +} + void copy_and_increment1(const std::vector &v) { auto i1 = v.begin(); diff --git a/clang/test/Analysis/kmalloc-linux.c b/clang/test/Analysis/kmalloc-linux.c index f183446bc0638..ccb6188a51b3d 100644 --- a/clang/test/Analysis/kmalloc-linux.c +++ b/clang/test/Analysis/kmalloc-linux.c @@ -1,10 +1,10 @@ // RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux %s -#include "Inputs/system-header-simulator.h" - #define __GFP_ZERO 0x8000 #define NULL ((void *)0) +typedef __typeof(sizeof(int)) size_t; + void *kmalloc(size_t, int); struct test { @@ -56,3 +56,54 @@ void test_indeterminate(int flags) { } kfree(list); } + +typedef unsigned long long uint64_t; + +struct malloc_type; + +void *malloc(unsigned long size, struct malloc_type *mtp, int flags); + +void test_3arg_malloc(struct malloc_type *mtp) { + struct test **list, *t; + int i; + + list = malloc(sizeof(*list) * 10, mtp, __GFP_ZERO); + if (list == NULL) + return; + + for (i = 0; i < 10; i++) { + t = list[i]; + foo(t); + } + kfree(list); // no-warning +} + +void test_3arg_malloc_nonzero(struct malloc_type *mtp) { + struct test **list, *t; + int i; + + list = malloc(sizeof(*list) * 10, mtp, 0); + if (list == NULL) + return; + + for (i = 0; i < 10; i++) { + t = list[i]; // expected-warning{{undefined}} + foo(t); + } + kfree(list); +} + +void test_3arg_malloc_indeterminate(struct malloc_type *mtp, int flags) { + struct test **list, *t; + int i; + + list = alloc(sizeof(*list) * 10, mtp, flags); + if (list == NULL) + return; + + for (i = 0; i < 10; i++) { + t = list[i]; // expected-warning{{undefined}} + foo(t); + } + kfree(list); +} diff --git a/clang/test/Analysis/malloc-annotations.cpp b/clang/test/Analysis/malloc-annotations.cpp new file mode 100644 index 0000000000000..0aac655d19c48 --- /dev/null +++ b/clang/test/Analysis/malloc-annotations.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_analyze_cc1 -analyzer-store=region -verify \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \ +// RUN: -analyzer-checker=alpha.core.CastSize \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-config unix.DynamicMemoryModeling:Optimistic=true %s + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); + +struct MemoryAllocator { + void __attribute((ownership_returns(malloc))) * my_malloc(size_t); + void __attribute((ownership_takes(malloc, 2))) my_free(void *); + void __attribute((ownership_holds(malloc, 2))) my_hold(void *); +}; + +void *myglobalpointer; + +struct stuff { + void *somefield; +}; + +struct stuff myglobalstuff; + +void af1(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + return; // expected-warning{{Potential leak of memory pointed to by}} +} + +void af1_b(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); +} // expected-warning{{Potential leak of memory pointed to by}} + +void af1_c(MemoryAllocator &Alloc) { + myglobalpointer = Alloc.my_malloc(12); // no-warning +} + +// Test that we can pass out allocated memory via pointer-to-pointer. +void af1_e(MemoryAllocator &Alloc, void **pp) { + *pp = Alloc.my_malloc(42); // no-warning +} + +void af1_f(MemoryAllocator &Alloc, struct stuff *somestuff) { + somestuff->somefield = Alloc.my_malloc(12); // no-warning +} + +// Allocating memory for a field via multiple indirections to our arguments is OK. +void af1_g(MemoryAllocator &Alloc, struct stuff **pps) { + *pps = (struct stuff *)Alloc.my_malloc(sizeof(struct stuff)); // no-warning + (*pps)->somefield = Alloc.my_malloc(42); // no-warning +} + +void af2(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + Alloc.my_free(p); + free(p); // expected-warning{{Attempt to free released memory}} +} + +void af2b(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + free(p); + Alloc.my_free(p); // expected-warning{{Attempt to free released memory}} +} + +void af2c(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + free(p); + Alloc.my_hold(p); // expected-warning{{Attempt to free released memory}} +} + +// No leak if malloc returns null. +void af2e(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + if (!p) + return; // no-warning + free(p); // no-warning +} + +// This case inflicts a possible double-free. +void af3(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + Alloc.my_hold(p); + free(p); // expected-warning{{Attempt to free non-owned memory}} +} + +void * af4(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + Alloc.my_free(p); + return p; // expected-warning{{Use of memory after it is freed}} +} + +// This case is (possibly) ok, be conservative +void * af5(MemoryAllocator &Alloc) { + void *p = Alloc.my_malloc(12); + Alloc.my_hold(p); + return p; // no-warning +} + diff --git a/clang/test/Analysis/osobject-retain-release.cpp b/clang/test/Analysis/osobject-retain-release.cpp index 42675fc70e785..41606a30c39f4 100644 --- a/clang/test/Analysis/osobject-retain-release.cpp +++ b/clang/test/Analysis/osobject-retain-release.cpp @@ -739,3 +739,18 @@ WeirdResult testOutParamWithWeirdResult() { return outParamWithWeirdResult(&obj); // no-warning } } // namespace weird_result + +namespace inherited_constructor_crash { +struct a { + a(int); +}; +struct b : a { + // This is an "inherited constructor". + using a::a; +}; +void test() { + // RetainCountChecker used to crash when looking for a summary + // for the inherited constructor invocation. + b(0); +} +} // namespace inherited_constructor_crash diff --git a/clang/test/Analysis/uninit-asm-goto.cpp b/clang/test/Analysis/uninit-asm-goto.cpp new file mode 100644 index 0000000000000..1d573b90016ef --- /dev/null +++ b/clang/test/Analysis/uninit-asm-goto.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -Wuninitialized -verify %s +// expected-no-diagnostics + +int test1(int x) { + int y; + asm goto("nop" : "=r"(y) : "r"(x) : : err); + return y; + err: + return -1; +} diff --git a/clang/test/Analysis/vfork.c b/clang/test/Analysis/vfork.c index da1b5da406657..8552b5fd02569 100644 --- a/clang/test/Analysis/vfork.c +++ b/clang/test/Analysis/vfork.c @@ -6,7 +6,7 @@ void foo(); // Ensure that child process is properly checked. -int f1(int x) { +int f1(int x, int y) { pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}} if (pid != 0) return 0; @@ -16,7 +16,29 @@ int f1(int x) { // Ensure that modifying pid is ok. pid = 1; // no-warning // Ensure that calling whitelisted routines is ok. - execl("", "", 0); // no-warning + switch (y) { + case 0: + execl("", "", 0); // no-warning + break; + case 1: + execle("", "", 0); // no-warning + break; + case 2: + execlp("", "", 0); // no-warning + break; + case 3: + execv("", NULL); // no-warning + break; + case 4: + execve("", NULL, NULL); // no-warning + break; + case 5: + execvp("", NULL); // no-warning + break; + case 6: + execvpe("", NULL, NULL); // no-warning + break; + } _exit(1); // no-warning break; case 1: diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp index 0138b88578f63..ef3b127ef82aa 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s typedef int fn; @@ -43,7 +43,7 @@ namespace std_example { int x = f(N::A()); #if __cplusplus <= 201703L - // expected-warning@-2 {{C++2a extension}} + // expected-warning@-2 {{C++20 extension}} #endif int y = g(N::A()); #if __cplusplus <= 201703L diff --git a/clang/test/CXX/conv/conv.fctptr/p1.cpp b/clang/test/CXX/conv/conv.fctptr/p1.cpp index be9c050af51ef..d18bd349b6882 100644 --- a/clang/test/CXX/conv/conv.fctptr/p1.cpp +++ b/clang/test/CXX/conv/conv.fctptr/p1.cpp @@ -11,7 +11,7 @@ Nothrow S::*c; Throw S::*d; void test() { - a = b; // expected-error {{assigning to 'Nothrow *' (aka 'void (*)() noexcept') from incompatible type 'Throw *' (aka 'void (*)()'): different exception specifications}} + a = b; // expected-error {{incompatible function pointer types assigning to 'Nothrow *' (aka 'void (*)() noexcept') from 'Throw *' (aka 'void (*)()')}} b = a; c = d; // expected-error {{assigning to 'Nothrow S::*' from incompatible type 'Throw S::*': different exception specifications}} d = c; diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp index bdf829210e0fb..3d3223cda7560 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++2a -verify -Wc++2a-extensions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify -Wc++20-extensions %s // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -Wc++17-extensions %s -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT -Wc++17-extensions -Wc++2a-extensions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT -Wc++17-extensions -Wc++20-extensions %s struct [[nodiscard]] S {}; S get_s(); @@ -73,7 +73,7 @@ LaterReason get_later_reason(); [[nodiscard("conflicting reason")]] int conflicting_reason(); [[nodiscard("special reason")]] int conflicting_reason(); -void cxx2a_use() { +void cxx20_use() { get_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: reason}} get_later_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: later reason}} another_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: another reason}} @@ -130,15 +130,15 @@ void usage() { // expected-warning@12 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@13 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@29 {{use of the 'nodiscard' attribute is a C++17 extension}} -// expected-warning@65 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@67 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@71 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@73 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@74 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@84 {{use of the 'nodiscard' attribute is a C++2a extension}} +// expected-warning@65 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@67 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@71 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@73 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@74 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@84 {{use of the 'nodiscard' attribute is a C++20 extension}} // expected-warning@86 {{use of the 'nodiscard' attribute is a C++17 extension}} -// expected-warning@87 {{use of the 'nodiscard' attribute is a C++2a extension}} +// expected-warning@87 {{use of the 'nodiscard' attribute is a C++20 extension}} // expected-warning@91 {{use of the 'nodiscard' attribute is a C++17 extension}} -// expected-warning@92 {{use of the 'nodiscard' attribute is a C++2a extension}} -// expected-warning@95 {{use of the 'nodiscard' attribute is a C++2a extension}} +// expected-warning@92 {{use of the 'nodiscard' attribute is a C++20 extension}} +// expected-warning@95 {{use of the 'nodiscard' attribute is a C++20 extension}} #endif diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 59c2ee7d936e3..9b0e7cc60f101 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s -// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s -// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++14-extensions -Werror=c++20-extensions %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++14 -DCXX14 -Werror=c++20-extensions %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++20 -DCXX14 -DCXX20 %s namespace N { typedef char C; @@ -54,11 +54,11 @@ struct T : SS, NonLiteral { // - its return type shall be a literal type; constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} constexpr void VoidReturn() const { return; } -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{constexpr function's return type 'void' is not a literal type}} #endif constexpr ~T(); -#ifndef CXX2A +#ifndef CXX20 // expected-error@-2 {{destructor cannot be declared constexpr}} #endif typedef NonLiteral F() const; @@ -78,7 +78,7 @@ struct T : SS, NonLiteral { // don't have a literal return type. Defaulted assignment operators can't be // constexpr since they can't be const. constexpr T &operator=(const T&) = default; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} // expected-warning@-3 {{C++14}} #else @@ -87,14 +87,14 @@ struct T : SS, NonLiteral { }; constexpr int T::OutOfLineVirtual() const { return 0; } -#ifdef CXX1Y +#ifdef CXX14 struct T2 { int n = 0; constexpr T2 &operator=(const T2&) = default; // ok }; struct T3 { constexpr T3 &operator=(const T3&) const = default; -#ifndef CXX2A +#ifndef CXX20 // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} #else // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}} @@ -138,56 +138,56 @@ constexpr int AllowedStmtsCXX11() { return sizeof(K) + sizeof(C) + sizeof(K); } -// or a compound-statement that does not contain [CXX1Y] -constexpr int DisallowedStmtsCXX1Y_1(bool b) { +// or a compound-statement that does not contain [C++14] +constexpr int DisallowedStmtsCXX14_1(bool b) { // - an asm-definition if (b) asm("int3"); -#if !defined(CXX2A) - // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}} +#if !defined(CXX20) + // expected-error@-2 {{use of this statement in a constexpr function is a C++20 extension}} #endif return 0; } -constexpr int DisallowedStmtsCXX1Y_2() { +constexpr int DisallowedStmtsCXX14_2() { // - a goto statement goto x; // expected-error {{statement not allowed in constexpr function}} x: return 0; } -constexpr int DisallowedStmtsCXX1Y_2_1() { +constexpr int DisallowedStmtsCXX14_2_1() { try { return 0; } catch (...) { merp: goto merp; // expected-error {{statement not allowed in constexpr function}} } } -constexpr int DisallowedStmtsCXX1Y_3() { +constexpr int DisallowedStmtsCXX14_3() { // - a try-block, try {} catch (...) {} -#if !defined(CXX2A) - // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}} +#if !defined(CXX20) + // expected-error@-2 {{use of this statement in a constexpr function is a C++20 extension}} #endif return 0; } -constexpr int DisallowedStmtsCXX1Y_4() { +constexpr int DisallowedStmtsCXX14_4() { // - a definition of a variable of non-literal type NonLiteral nl; // expected-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function}} return 0; } -constexpr int DisallowedStmtsCXX1Y_5() { +constexpr int DisallowedStmtsCXX14_5() { // - a definition of a variable of static storage duration static constexpr int n = 123; // expected-error {{static variable not permitted in a constexpr function}} return n; } -constexpr int DisallowedStmtsCXX1Y_6() { +constexpr int DisallowedStmtsCXX14_6() { // - a definition of a variable of thread storage duration thread_local constexpr int n = 123; // expected-error {{thread_local variable not permitted in a constexpr function}} return n; } -constexpr int DisallowedStmtsCXX1Y_7() { +constexpr int DisallowedStmtsCXX14_7() { // - a definition of a variable for which no initialization is performed int n; -#ifndef CXX2A +#ifndef CXX20 // expected-error@-2 {{uninitialized variable in a constexpr function}} #endif return 0; @@ -195,28 +195,28 @@ constexpr int DisallowedStmtsCXX1Y_7() { constexpr int ForStmt() { for (int n = 0; n < 10; ++n) -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{statement not allowed in constexpr function}} #endif return 0; } constexpr int VarDecl() { int a = 0; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{variable declaration in a constexpr function is a C++14 extension}} #endif return 0; } constexpr int ConstexprVarDecl() { constexpr int a = 0; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{variable declaration in a constexpr function is a C++14 extension}} #endif return 0; } constexpr int VarWithCtorDecl() { Literal a; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{variable declaration in a constexpr function is a C++14 extension}} #endif return 0; @@ -224,7 +224,7 @@ constexpr int VarWithCtorDecl() { NonLiteral nl; constexpr NonLiteral &ExternNonLiteralVarDecl() { extern NonLiteral nl; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{variable declaration in a constexpr function is a C++14 extension}} #endif return nl; @@ -232,28 +232,28 @@ constexpr NonLiteral &ExternNonLiteralVarDecl() { static_assert(&ExternNonLiteralVarDecl() == &nl, ""); constexpr int FuncDecl() { constexpr int ForwardDecl(int); -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{use of this statement in a constexpr function is a C++14 extension}} #endif return ForwardDecl(42); } constexpr int ClassDecl1() { typedef struct { } S1; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr function is a C++14 extension}} #endif return 0; } constexpr int ClassDecl2() { using S2 = struct { }; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr function is a C++14 extension}} #endif return 0; } constexpr int ClassDecl3() { struct S3 { }; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr function is a C++14 extension}} #endif return 0; @@ -262,7 +262,7 @@ constexpr int NoReturn() {} // expected-error {{no return statement in constexpr constexpr int MultiReturn() { return 0; return 0; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{multiple return statements in constexpr function}} // expected-note@-4 {{return statement}} #endif @@ -310,7 +310,7 @@ namespace std_example { } constexpr int abs(int x) { if (x < 0) -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{C++14}} #endif x = -x; @@ -322,7 +322,7 @@ namespace std_example { } constexpr int uninit() { int a; -#ifndef CXX2A +#ifndef CXX20 // expected-error@-2 {{uninitialized}} #endif return a; @@ -330,7 +330,7 @@ namespace std_example { constexpr int prev(int x) { return --x; } -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-4 {{never produces a constant expression}} // expected-note@-4 {{subexpression}} #endif @@ -339,7 +339,7 @@ namespace std_example { while (--n > 0) r *= x; return r; } -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-5 {{C++14}} // expected-error@-5 {{statement not allowed}} #endif diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 39088042251f0..aed2f29f67c3a 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s -// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s -// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s +// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++14-extensions -Werror=c++20-extensions %s +// RUN: %clang_cc1 -verify -std=c++14 -fcxx-exceptions -DCXX14 -Werror=c++20-extensions %s +// RUN: %clang_cc1 -verify -std=c++20 -fcxx-exceptions -DCXX14 -DCXX2A %s namespace N { typedef char C; @@ -52,10 +52,10 @@ struct U { constexpr U() try #ifndef CXX2A - // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}} + // expected-error@-2 {{function try block in constexpr constructor is a C++20 extension}} #endif : u() { -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} #endif } catch (...) { @@ -92,43 +92,43 @@ struct V { constexpr V(int(&)[1]) { for (int n = 0; n < 10; ++n) /**/; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-3 {{statement not allowed in constexpr constructor}} #endif } constexpr V(int(&)[2]) { constexpr int a = 0; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{variable declaration in a constexpr constructor is a C++14 extension}} #endif } constexpr V(int(&)[3]) { constexpr int ForwardDecl(int); -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} #endif } constexpr V(int(&)[4]) { typedef struct { } S1; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}} #endif } constexpr V(int(&)[5]) { using S2 = struct { }; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}} #endif } constexpr V(int(&)[6]) { struct S3 { }; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}} #endif } constexpr V(int(&)[7]) { return; -#ifndef CXX1Y +#ifndef CXX14 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} #endif } diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp index 6e9b45903d394..9614a17241996 100644 --- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp +++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify=expected,pre2a %s -std=c++11 -// RUN: %clang_cc1 -verify=expected,pre2a %s -std=c++17 -// RUN: %clang_cc1 -verify=expected %s -std=c++2a +// RUN: %clang_cc1 -verify=expected,pre20 %s -std=c++11 +// RUN: %clang_cc1 -verify=expected,pre20 %s -std=c++17 +// RUN: %clang_cc1 -verify=expected %s -std=c++20 // A function that is explicitly defaulted shall struct A { - // -- be a special member function [C++2a: or a comparison operator function], + // -- be a special member function [C++20: or a comparison operator function], A(int) = default; #if __cplusplus <= 201703L // expected-error@-2 {{only special member functions may be defaulted}} @@ -14,13 +14,13 @@ struct A { A(A) = default; // expected-error {{must pass its first argument by reference}} void f(A) = default; // expected-error-re {{only special member functions{{( and comparison operators)?}} may be defaulted}} - bool operator==(const A&) const = default; // pre2a-warning {{defaulted comparison operators are a C++20 extension}} - bool operator!=(const A&) const = default; // pre2a-warning {{defaulted comparison operators are a C++20 extension}} - bool operator<(const A&) const = default; // pre2a-error {{only special member functions may be defaulted}} - bool operator>(const A&) const = default; // pre2a-error {{only special member functions may be defaulted}} - bool operator<=(const A&) const = default; // pre2a-error {{only special member functions may be defaulted}} - bool operator>=(const A&) const = default; // pre2a-error {{only special member functions may be defaulted}} - bool operator<=>(const A&) const = default; // pre2a-error 1+{{}} pre2a-warning {{'<=>' is a single token in C++2a}} + bool operator==(const A&) const = default; // pre20-warning {{defaulted comparison operators are a C++20 extension}} + bool operator!=(const A&) const = default; // pre20-warning {{defaulted comparison operators are a C++20 extension}} + bool operator<(const A&) const = default; // pre20-error {{only special member functions may be defaulted}} + bool operator>(const A&) const = default; // pre20-error {{only special member functions may be defaulted}} + bool operator<=(const A&) const = default; // pre20-error {{only special member functions may be defaulted}} + bool operator>=(const A&) const = default; // pre20-error {{only special member functions may be defaulted}} + bool operator<=>(const A&) const = default; // pre20-error 1+{{}} pre20-warning {{'<=>' is a single token in C++20}} A operator+(const A&) const = default; // expected-error-re {{only special member functions{{( and comparison operators)?}} may be defaulted}} diff --git a/clang/test/CXX/dcl.decl/p4-0x.cpp b/clang/test/CXX/dcl.decl/p4-0x.cpp index 35177a0386977..3a7b21568044f 100644 --- a/clang/test/CXX/dcl.decl/p4-0x.cpp +++ b/clang/test/CXX/dcl.decl/p4-0x.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// expected-no-diagnostics struct X { void f() &; @@ -7,3 +6,15 @@ struct X { }; void (X::*pmf)() & = &X::f; + +void fn() { + void (*[[attr]] fn_ptr)() = &fn; // expected-warning{{unknown attribute 'attr' ignored}} + void (*[[attrA]] *[[attrB]] fn_ptr_ptr)() = &fn_ptr; // expected-warning{{unknown attribute 'attrA' ignored}} expected-warning{{unknown attribute 'attrB' ignored}} + + void (&[[attr]] fn_lref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}} + void (&&[[attr]] fn_rref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}} + + int i[5]; + int (*[[attr(i[1])]] pi); // expected-warning{{unknown attribute 'attr' ignored}} + pi = &i[0]; +} diff --git a/clang/test/CXX/drs/dr2xx.cpp b/clang/test/CXX/drs/dr2xx.cpp index 905a2b07888d5..125caad554956 100644 --- a/clang/test/CXX/drs/dr2xx.cpp +++ b/clang/test/CXX/drs/dr2xx.cpp @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // PR13819 -- __SIZE_TYPE__ is incompatible. typedef __SIZE_TYPE__ size_t; // expected-error 0-1 {{extension}} @@ -449,8 +449,8 @@ namespace dr241 { // dr241: yes template void g(T t); // expected-note {{candidate}} } void h(A::B b) { - f<3>(b); // expected-error 0-1{{C++2a extension}} expected-error {{no matching}} - g<3>(b); // expected-error 0-1{{C++2a extension}} + f<3>(b); // expected-error 0-1{{C++20 extension}} expected-error {{no matching}} + g<3>(b); // expected-error 0-1{{C++20 extension}} A::f<3>(b); // expected-error {{no matching}} A::g<3>(b); C::f<3>(b); // expected-error {{no matching}} diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp index 4ce624974bbef..a5edc32fa48c9 100644 --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -372,7 +372,7 @@ namespace dr330 { // dr330: 7 s = q; // expected-error {{incompatible}} s = q2; // expected-error {{incompatible}} s = t; // ok, adding const - t = s; // expected-error {{incompatible}} + t = s; // expected-error {{discards qualifiers}} (void) const_cast

(q); (void) const_cast

(q2); (void) const_cast(p); diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp index 4c4ed7767ecd2..1ba48ee95b209 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking namespace std { struct type_info {}; @@ -506,7 +506,7 @@ namespace dr647 { // dr647: yes constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}} constexpr C() try {} catch (...) {} #if __cplusplus <= 201703L - // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}} + // expected-error@-2 {{function try block in constexpr constructor is a C++20 extension}} #endif #if __cplusplus < 201402L // expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}} @@ -1070,7 +1070,7 @@ namespace dr687 { // dr687 (9 c++20, but the issue is still considered open) // This is valid in C++20. g(a); #if __cplusplus <= 201703L - // expected-error@-2 {{C++2a extension}} + // expected-error@-2 {{C++20 extension}} #endif // This is not. diff --git a/clang/test/CXX/except/except.handle/p16.cpp b/clang/test/CXX/except/except.handle/p16.cpp index 0810be108e41a..86ced1ae42879 100644 --- a/clang/test/CXX/except/except.handle/p16.cpp +++ b/clang/test/CXX/except/except.handle/p16.cpp @@ -11,12 +11,12 @@ class X { public: X(const X &) { int *ip = 0; - ptr = ip; // expected-error{{assigning to 'float *' from incompatible type 'int *'}} + ptr = ip; // expected-error{{incompatible pointer types assigning to 'float *' from 'int *'}} } ~X() { float *fp = 0; - ptr = fp; // expected-error{{assigning to 'int *' from incompatible type 'float *'}} + ptr = fp; // expected-error{{incompatible pointer types assigning to 'int *' from 'float *'}} } }; diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index cc6380e044fbf..c418767f8d12d 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -424,8 +424,26 @@ namespace PseudoDtor { int k; typedef int I; struct T { - int n : (k.~I(), 1); // cxx11-warning {{constant expression}} cxx11-note {{pseudo-destructor}} + int n : (k.~I(), 1); // expected-error {{constant expression}} expected-note {{visible outside that expression}} }; + + // FIXME: It's unclear whether this should be accepted in C++20 mode. The parameter is destroyed twice here. + constexpr int f(int a = 1) { // cxx11-error {{constant expression}} + return ( + a.~I(), // cxx11-note 2{{pseudo-destructor}} + 0); + } + static_assert(f() == 0, ""); // cxx11-error {{constant expression}} cxx11-note {{in call}} + + // This is OK in C++20: the union has no active member after the + // pseudo-destructor call, so the union destructor has no effect. + union U { int x; }; + constexpr int g(U u = {1}) { // cxx11-error {{constant expression}} + return ( + u.x.~I(), // cxx11-note 2{{pseudo-destructor}} + 0); + } + static_assert(g() == 0, ""); // cxx11-error {{constant expression}} cxx11-note {{in call}} } // - increment or decrement operations (5.2.6, 5.3.2); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp index 1cc1fd974ca5d..7c95245da4ca2 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -verify -Wno-c++1y-extensions +// RUN: %clang_cc1 -std=c++11 %s -verify -Wno-c++14-extensions class X0 { void explicit_capture() { @@ -8,7 +8,7 @@ class X0 { (void)[this, this] () {}; // expected-error {{'this' can appear only once}} (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}} (void)[=, &foo] () {}; - (void)[=, this] () {}; // expected-warning {{C++2a extension}} + (void)[=, this] () {}; // expected-warning {{C++20 extension}} (void)[&, foo] () {}; (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} (void)[&, this] () {}; @@ -23,7 +23,7 @@ struct S2 { void S2::f(int i) { (void)[&, i]{ }; (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}} - (void)[=, this]{ }; // expected-warning{{C++2a extension}} + (void)[=, this]{ }; // expected-warning{{C++20 extension}} (void)[=]{ this->g(i); }; (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} (void)[i(0), i(1)]{ }; // expected-error{{'i' can appear only once in a capture list}} diff --git a/clang/test/CXX/expr/p13.cpp b/clang/test/CXX/expr/p13.cpp index 0f22ce0b7cebc..44e7140ceb126 100644 --- a/clang/test/CXX/expr/p13.cpp +++ b/clang/test/CXX/expr/p13.cpp @@ -11,7 +11,7 @@ using E = void (Y::*)() noexcept; using F = void (Y::*)(); void f(A a, B b, C c, D d, E e, F f, bool k) { - a = k ? a : b; // expected-error {{different exception specifications}} + a = k ? a : b; // expected-error {{incompatible function pointer types assigning to 'A' (aka 'void (*)() noexcept') from 'void (*)()'}} b = k ? a : b; c = k ? c : d; // expected-error {{different exception specifications}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp index 1c2ea7ebde717..16666d185b06e 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp @@ -14,7 +14,7 @@ struct X::Inner { template<> template void X::f(int x, U y) { - x = y; // expected-error{{incompatible type}} + x = y; // expected-error{{incompatible pointer to integer conversion}} } void test(X xi, X xl, float *fp) { diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp index 290a874296e1b..b21db7f51f1ae 100644 --- a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp @@ -11,7 +11,7 @@ struct X0 { template void X0::f(T& t) { - t = 1; // expected-error{{incompatible type}} + t = 1; // expected-error{{incompatible integer to pointer conversion}} } template diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp index 86490175f0c39..3e9b4f8fccf41 100644 --- a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp @@ -3,7 +3,7 @@ template struct X0 { void f(T &t) { - t = 1; // expected-error{{incompatible type}} + t = 1; // expected-error{{incompatible integer to pointer conversion}} } void g(T &t); @@ -15,7 +15,7 @@ struct X0 { template inline void X0::g(T & t) { - t = 1; // expected-error{{incompatible type}} + t = 1; // expected-error{{incompatible integer to pointer conversion}} } template @@ -37,12 +37,12 @@ int *&test(X0 xi, int *ip) { template void f0(T& t) { - t = 1; // expected-error{{incompatible type}} + t = 1; // expected-error{{incompatible integer to pointer conversion}} } template inline void f1(T& t) { - t = 1; // expected-error 2{{incompatible type}} + t = 1; // expected-error 2{{incompatible integer to pointer conversion}} } extern template void f0<>(int *&); diff --git a/clang/test/CodeCompletion/included-symlinks.cpp b/clang/test/CodeCompletion/included-symlinks.cpp new file mode 100644 index 0000000000000..bccaaa6162143 --- /dev/null +++ b/clang/test/CodeCompletion/included-symlinks.cpp @@ -0,0 +1,16 @@ +// REQUIRES: shell +// RUN: rm -rf %t && mkdir -p %t/real/myproj && mkdir -p %t/links +// RUN: touch %t/real/foo.h && ln -s %t/real/foo.h %t/links/foo.h +// RUN: touch %t/real/foobar.h && ln -s %t/real/foobar.h %t/links/foobar.h +// RUN: touch %t/real/myproj/test.h && ln -s %t/real/myproj %t/links/myproj + +// Suggest symlinked header files. +#include "foo.h" +// RUN: %clang -fsyntax-only -I%t/links -Xclang -code-completion-at=%s:8:13 %s | FileCheck -check-prefix=CHECK-1 %s +// CHECK-1: foo.h" +// CHECK-1: foobar.h" + +// Suggest symlinked folder. +#include "mypr" +// RUN: %clang -fsyntax-only -I%t/links -Xclang -code-completion-at=%s:14:13 %s | FileCheck -check-prefix=CHECK-2 %s +// CHECK-2: myproj/ diff --git a/clang/test/CodeGen/PR44896.ll b/clang/test/CodeGen/PR44896.ll new file mode 100644 index 0000000000000..a4d344579870b --- /dev/null +++ b/clang/test/CodeGen/PR44896.ll @@ -0,0 +1,15 @@ +; RUN: %clang -fdiscard-value-names -S %s -o /dev/null 2>&1 | FileCheck --check-prefix=WARNING %s +; RUN: %clang -S %s -o /dev/null 2>&1 | FileCheck --check-prefix=NOWARNING %s +; RUN: %clang_cc1 -S -emit-llvm %s -discard-value-names -o /dev/null +; PR 44896 + +; WARNING: ignoring -fdiscard-value-names for LLVM Bitcode +; NOWARNING-NOT: ignoring -fdiscard-value-names for LLVM Bitcode + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64--linux-gnu" + +define linkonce i8* @b(i8* %a) { + ret i8* %a +} + diff --git a/clang/test/CodeGen/aarch64-sve.c b/clang/test/CodeGen/aarch64-sve.c index b596fbbfcc8d9..bb4512d5ed93b 100644 --- a/clang/test/CodeGen/aarch64-sve.c +++ b/clang/test/CodeGen/aarch64-sve.c @@ -1,9 +1,51 @@ // RUN: not %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ -// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s +// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s -check-prefix=CHECK-DEBUG +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefix=CHECK -// Placeholder test for SVE types +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVInt8_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVInt16_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVInt32_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVInt64_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVUint8_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVUint16_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVUint32_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVUint64_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVFloat16_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVFloat32_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVFloat64_t' +// CHECK-DEBUG: cannot yet generate debug info for SVE type '__SVBool_t' -// CHECK: cannot yet generate code for SVE type '__SVInt8_t' -// CHECK: cannot yet generate debug info for SVE type '__SVInt8_t' +// CHECK: @ptr = common global * null, align 8 +// CHECK: %s8 = alloca , align 16 +// CHECK: %s16 = alloca , align 16 +// CHECK: %s32 = alloca , align 16 +// CHECK: %s64 = alloca , align 16 +// CHECK: %u8 = alloca , align 16 +// CHECK: %u16 = alloca , align 16 +// CHECK: %u32 = alloca , align 16 +// CHECK: %u64 = alloca , align 16 +// CHECK: %f16 = alloca , align 16 +// CHECK: %f32 = alloca , align 16 +// CHECK: %f64 = alloca , align 16 +// CHECK: %b8 = alloca , align 2 __SVInt8_t *ptr; + +void test_locals(void) { + __SVInt8_t s8; + __SVInt16_t s16; + __SVInt32_t s32; + __SVInt64_t s64; + + __SVUint8_t u8; + __SVUint16_t u16; + __SVUint32_t u32; + __SVUint64_t u64; + + __SVFloat16_t f16; + __SVFloat32_t f32; + __SVFloat64_t f64; + + __SVBool_t b8; +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/absneg.c b/clang/test/CodeGen/arm-mve-intrinsics/absneg.c new file mode 100644 index 0000000000000..db4253f3590b9 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/absneg.c @@ -0,0 +1,338 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vabsq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.fabs.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vabsq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vabsq(a); +#else /* POLYMORPHIC */ + return vabsq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vabsq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vabsq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vabsq(a); +#else /* POLYMORPHIC */ + return vabsq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vabsq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <16 x i8> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <16 x i8> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <16 x i1> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[A]] +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vabsq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vabsq(a); +#else /* POLYMORPHIC */ + return vabsq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vabsq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <8 x i16> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <8 x i16> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <8 x i1> [[TMP0]], <8 x i16> [[TMP1]], <8 x i16> [[A]] +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vabsq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vabsq(a); +#else /* POLYMORPHIC */ + return vabsq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vabsq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i32> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP1]], <4 x i32> [[A]] +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vabsq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vabsq(a); +#else /* POLYMORPHIC */ + return vabsq_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <16 x i8> [[A:%.*]], +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vmvnq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <8 x i16> [[A:%.*]], +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vmvnq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <4 x i32> [[A:%.*]], +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vmvnq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <16 x i8> [[A:%.*]], +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vmvnq_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <8 x i16> [[A:%.*]], +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +uint16x8_t test_vmvnq_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmvnq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = xor <4 x i32> [[A:%.*]], +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vmvnq_u32(uint32x4_t a) +{ +#ifdef POLYMORPHIC + return vmvnq(a); +#else /* POLYMORPHIC */ + return vmvnq_u32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vnegq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fneg <8 x half> [[A:%.*]] +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vnegq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vnegq(a); +#else /* POLYMORPHIC */ + return vnegq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vnegq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fneg <4 x float> [[A:%.*]] +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vnegq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vnegq(a); +#else /* POLYMORPHIC */ + return vnegq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vnegq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = sub <16 x i8> zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vnegq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vnegq(a); +#else /* POLYMORPHIC */ + return vnegq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vnegq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = sub <8 x i16> zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vnegq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vnegq(a); +#else /* POLYMORPHIC */ + return vnegq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vnegq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = sub <4 x i32> zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vnegq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vnegq(a); +#else /* POLYMORPHIC */ + return vnegq_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqabsq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp sgt <16 x i8> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = icmp eq <16 x i8> [[A]], +// CHECK-NEXT: [[TMP2:%.*]] = sub <16 x i8> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP3:%.*]] = select <16 x i1> [[TMP1]], <16 x i8> , <16 x i8> [[TMP2]] +// CHECK-NEXT: [[TMP4:%.*]] = select <16 x i1> [[TMP0]], <16 x i8> [[A]], <16 x i8> [[TMP3]] +// CHECK-NEXT: ret <16 x i8> [[TMP4]] +// +int8x16_t test_vqabsq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vqabsq(a); +#else /* POLYMORPHIC */ + return vqabsq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqabsq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp sgt <8 x i16> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = icmp eq <8 x i16> [[A]], +// CHECK-NEXT: [[TMP2:%.*]] = sub <8 x i16> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP3:%.*]] = select <8 x i1> [[TMP1]], <8 x i16> , <8 x i16> [[TMP2]] +// CHECK-NEXT: [[TMP4:%.*]] = select <8 x i1> [[TMP0]], <8 x i16> [[A]], <8 x i16> [[TMP3]] +// CHECK-NEXT: ret <8 x i16> [[TMP4]] +// +int16x8_t test_vqabsq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vqabsq(a); +#else /* POLYMORPHIC */ + return vqabsq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqabsq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp sgt <4 x i32> [[A:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[A]], +// CHECK-NEXT: [[TMP2:%.*]] = sub <4 x i32> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> , <4 x i32> [[TMP2]] +// CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[A]], <4 x i32> [[TMP3]] +// CHECK-NEXT: ret <4 x i32> [[TMP4]] +// +int32x4_t test_vqabsq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vqabsq(a); +#else /* POLYMORPHIC */ + return vqabsq_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqnegq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp eq <16 x i8> [[A:%.*]], +// CHECK-NEXT: [[TMP1:%.*]] = sub <16 x i8> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <16 x i1> [[TMP0]], <16 x i8> , <16 x i8> [[TMP1]] +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vqnegq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vqnegq(a); +#else /* POLYMORPHIC */ + return vqnegq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqnegq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp eq <8 x i16> [[A:%.*]], +// CHECK-NEXT: [[TMP1:%.*]] = sub <8 x i16> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <8 x i1> [[TMP0]], <8 x i16> , <8 x i16> [[TMP1]] +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vqnegq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vqnegq(a); +#else /* POLYMORPHIC */ + return vqnegq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqnegq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp eq <4 x i32> [[A:%.*]], +// CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> zeroinitializer, [[A]] +// CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> , <4 x i32> [[TMP1]] +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqnegq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vqnegq(a); +#else /* POLYMORPHIC */ + return vqnegq_s32(a); +#endif /* POLYMORPHIC */ +} + diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vaddq.c b/clang/test/CodeGen/arm-mve-intrinsics/vaddq.c index 1810c7e89b54b..1904c6e835c78 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vaddq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vaddq.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s #include @@ -95,3 +95,113 @@ float16x8_t test_vaddq_x_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) return vaddq_x_f16(a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vaddq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = add <4 x i32> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vaddq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vaddq(a, b); +#else /* POLYMORPHIC */ + return vaddq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vaddq_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[B_COERCE:%.*]] to i32 +// CHECK-NEXT: [[TMP_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[TMP0]] to i16 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP_0_EXTRACT_TRUNC]] to half +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> undef, half [[TMP1]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = fadd <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <8 x half> [[TMP2]] +// +float16x8_t test_vaddq_n_f16(float16x8_t a, float16_t b) +{ +#ifdef POLYMORPHIC + return vaddq(a, b); +#else /* POLYMORPHIC */ + return vaddq_n_f16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vaddq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.add.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vaddq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vaddq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vaddq_m_n_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> undef, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.add.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x float> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vaddq_m_n_f32(float32x4_t inactive, float32x4_t a, float32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vaddq_m_n_f32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vaddq_x_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.add.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vaddq_x_n_u16(uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vaddq_x(a, b, p); +#else /* POLYMORPHIC */ + return vaddq_x_n_u16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vaddq_x_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[B_COERCE:%.*]] to i32 +// CHECK-NEXT: [[TMP_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[TMP0]] to i16 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP_0_EXTRACT_TRUNC]] to half +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> undef, half [[TMP1]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP3:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP2]]) +// CHECK-NEXT: [[TMP4:%.*]] = call <8 x half> @llvm.arm.mve.add.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[DOTSPLAT]], <8 x i1> [[TMP3]], <8 x half> undef) +// CHECK-NEXT: ret <8 x half> [[TMP4]] +// +float16x8_t test_vaddq_x_n_f16(float16x8_t a, float16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vaddq_x(a, b, p); +#else /* POLYMORPHIC */ + return vaddq_x_n_f16(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vbrsrq.c b/clang/test/CodeGen/arm-mve-intrinsics/vbrsrq.c new file mode 100644 index 0000000000000..e1fd5993cc74a --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vbrsrq.c @@ -0,0 +1,92 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vbrsrq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vbrsr.v4i32(<4 x i32> [[A:%.*]], i32 [[B:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vbrsrq_n_u32(uint32x4_t a, int32_t b) { +#ifdef POLYMORPHIC + return vbrsrq(a, b); +#else /* POLYMORPHIC */ + return vbrsrq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vbrsrq_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.arm.mve.vbrsr.v8f16(<8 x half> [[A:%.*]], i32 [[B:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vbrsrq_n_f16(float16x8_t a, int32_t b) { +#ifdef POLYMORPHIC + return vbrsrq(a, b); +#else /* POLYMORPHIC */ + return vbrsrq_n_f16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vbrsrq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.vbrsr.predicated.v16i8.v16i1(<16 x i8> [[INACTIVE:%.*]], <16 x i8> [[A:%.*]], i32 [[B:%.*]], <16 x i1> [[TMP1]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vbrsrq_m_n_s8(int8x16_t inactive, int8x16_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vbrsrq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vbrsrq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vbrsrq_m_n_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.vbrsr.predicated.v4f32.v4i1(<4 x float> [[INACTIVE:%.*]], <4 x float> [[A:%.*]], i32 [[B:%.*]], <4 x i1> [[TMP1]]) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vbrsrq_m_n_f32(float32x4_t inactive, float32x4_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vbrsrq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vbrsrq_m_n_f32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vbrsrq_x_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vbrsr.predicated.v8i16.v8i1(<8 x i16> undef, <8 x i16> [[A:%.*]], i32 [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vbrsrq_x_n_u16(uint16x8_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vbrsrq_x(a, b, p); +#else /* POLYMORPHIC */ + return vbrsrq_x_n_u16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vbrsrq_x_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x half> @llvm.arm.mve.vbrsr.predicated.v8f16.v8i1(<8 x half> undef, <8 x half> [[A:%.*]], i32 [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x half> [[TMP2]] +// +float16x8_t test_vbrsrq_x_n_f16(float16x8_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vbrsrq_x(a, b, p); +#else /* POLYMORPHIC */ + return vbrsrq_x_n_f16(a, b, p); +#endif /* POLYMORPHIC */ +} + diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vclz.c b/clang/test/CodeGen/arm-mve-intrinsics/vclz.c new file mode 100644 index 0000000000000..7a2ebe0a627af --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vclz.c @@ -0,0 +1,132 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vclzq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vclzq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclzq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vclzq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclzq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vclzq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclzq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vclzq_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclzq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +uint16x8_t test_vclzq_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclzq_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[A:%.*]], i1 false) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vclzq_u32(uint32x4_t a) +{ +#ifdef POLYMORPHIC + return vclzq(a); +#else /* POLYMORPHIC */ + return vclzq_u32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclsq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.mve.vcls.v16i8(<16 x i8> [[A:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vclsq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vclsq(a); +#else /* POLYMORPHIC */ + return vclsq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclsq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vcls.v8i16(<8 x i16> [[A:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vclsq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vclsq(a); +#else /* POLYMORPHIC */ + return vclsq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vclsq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vcls.v4i32(<4 x i32> [[A:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vclsq_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vclsq(a); +#else /* POLYMORPHIC */ + return vclsq_s32(a); +#endif /* POLYMORPHIC */ +} + diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vcvt.c b/clang/test/CodeGen/arm-mve-intrinsics/vcvt.c index a1c99de62ebb1..3220100d7b894 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vcvt.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vcvt.c @@ -4,6 +4,102 @@ #include +// CHECK-LABEL: @test_vcvtq_f16_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = sitofp <8 x i16> [[A:%.*]] to <8 x half> +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vcvtq_f16_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vcvtq(a); +#else /* POLYMORPHIC */ + return vcvtq_f16_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vcvtq_f16_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = uitofp <8 x i16> [[A:%.*]] to <8 x half> +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vcvtq_f16_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vcvtq(a); +#else /* POLYMORPHIC */ + return vcvtq_f16_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vcvtq_f32_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = sitofp <4 x i32> [[A:%.*]] to <4 x float> +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vcvtq_f32_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vcvtq(a); +#else /* POLYMORPHIC */ + return vcvtq_f32_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vcvtq_f32_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = uitofp <4 x i32> [[A:%.*]] to <4 x float> +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vcvtq_f32_u32(uint32x4_t a) +{ +#ifdef POLYMORPHIC + return vcvtq(a); +#else /* POLYMORPHIC */ + return vcvtq_f32_u32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vcvtq_s16_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fptosi <8 x half> [[A:%.*]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vcvtq_s16_f16(float16x8_t a) +{ + return vcvtq_s16_f16(a); +} + +// CHECK-LABEL: @test_vcvtq_s32_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fptosi <4 x float> [[A:%.*]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vcvtq_s32_f32(float32x4_t a) +{ + return vcvtq_s32_f32(a); +} + +// CHECK-LABEL: @test_vcvtq_u16_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fptoui <8 x half> [[A:%.*]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +uint16x8_t test_vcvtq_u16_f16(float16x8_t a) +{ + return vcvtq_u16_f16(a); +} + +// CHECK-LABEL: @test_vcvtq_u32_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = fptoui <4 x float> [[A:%.*]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vcvtq_u32_f32(float32x4_t a) +{ + return vcvtq_u32_f32(a); +} + // CHECK-LABEL: @test_vcvttq_f16_f32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.arm.mve.vcvt.narrow(<8 x half> [[A:%.*]], <4 x float> [[B:%.*]], i32 1) diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c b/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c index 2128d0801c6a8..e86f78b659c07 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c @@ -1382,8 +1382,8 @@ uint32x4_t test_vshlltq_n_u16(uint16x8_t a) // CHECK-LABEL: @test_vshllbq_m_n_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 6, i32 0, i32 0, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 6, i32 0, i32 0, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vshllbq_m_n_s8(int16x8_t inactive, int8x16_t a, mve_pred16_t p) @@ -1398,8 +1398,8 @@ int16x8_t test_vshllbq_m_n_s8(int16x8_t inactive, int8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshllbq_m_n_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 10, i32 0, i32 0, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 10, i32 0, i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vshllbq_m_n_s16(int32x4_t inactive, int16x8_t a, mve_pred16_t p) @@ -1414,8 +1414,8 @@ int32x4_t test_vshllbq_m_n_s16(int32x4_t inactive, int16x8_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshllbq_m_n_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 3, i32 1, i32 0, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 3, i32 1, i32 0, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vshllbq_m_n_u8(uint16x8_t inactive, uint8x16_t a, mve_pred16_t p) @@ -1430,8 +1430,8 @@ uint16x8_t test_vshllbq_m_n_u8(uint16x8_t inactive, uint8x16_t a, mve_pred16_t p // CHECK-LABEL: @test_vshllbq_m_n_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 14, i32 1, i32 0, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 14, i32 1, i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vshllbq_m_n_u16(uint32x4_t inactive, uint16x8_t a, mve_pred16_t p) @@ -1446,8 +1446,8 @@ uint32x4_t test_vshllbq_m_n_u16(uint32x4_t inactive, uint16x8_t a, mve_pred16_t // CHECK-LABEL: @test_vshlltq_m_n_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 4, i32 0, i32 1, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 4, i32 0, i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vshlltq_m_n_s8(int16x8_t inactive, int8x16_t a, mve_pred16_t p) @@ -1462,8 +1462,8 @@ int16x8_t test_vshlltq_m_n_s8(int16x8_t inactive, int8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_m_n_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 12, i32 0, i32 1, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 12, i32 0, i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vshlltq_m_n_s16(int32x4_t inactive, int16x8_t a, mve_pred16_t p) @@ -1478,8 +1478,8 @@ int32x4_t test_vshlltq_m_n_s16(int32x4_t inactive, int16x8_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_m_n_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 2, i32 1, i32 1, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 2, i32 1, i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vshlltq_m_n_u8(uint16x8_t inactive, uint8x16_t a, mve_pred16_t p) @@ -1494,8 +1494,8 @@ uint16x8_t test_vshlltq_m_n_u8(uint16x8_t inactive, uint8x16_t a, mve_pred16_t p // CHECK-LABEL: @test_vshlltq_m_n_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 9, i32 1, i32 1, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 9, i32 1, i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vshlltq_m_n_u16(uint32x4_t inactive, uint16x8_t a, mve_pred16_t p) @@ -1510,8 +1510,8 @@ uint32x4_t test_vshlltq_m_n_u16(uint32x4_t inactive, uint16x8_t a, mve_pred16_t // CHECK-LABEL: @test_vshllbq_x_n_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 1, i32 0, i32 0, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 1, i32 0, i32 0, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vshllbq_x_n_s8(int8x16_t a, mve_pred16_t p) @@ -1526,8 +1526,8 @@ int16x8_t test_vshllbq_x_n_s8(int8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshllbq_x_n_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 10, i32 0, i32 0, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 10, i32 0, i32 0, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vshllbq_x_n_s16(int16x8_t a, mve_pred16_t p) @@ -1542,8 +1542,8 @@ int32x4_t test_vshllbq_x_n_s16(int16x8_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshllbq_x_n_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 6, i32 1, i32 0, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 6, i32 1, i32 0, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vshllbq_x_n_u8(uint8x16_t a, mve_pred16_t p) @@ -1558,8 +1558,8 @@ uint16x8_t test_vshllbq_x_n_u8(uint8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshllbq_x_n_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 10, i32 1, i32 0, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 10, i32 1, i32 0, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vshllbq_x_n_u16(uint16x8_t a, mve_pred16_t p) @@ -1574,8 +1574,8 @@ uint32x4_t test_vshllbq_x_n_u16(uint16x8_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_x_n_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 2, i32 0, i32 1, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 2, i32 0, i32 1, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vshlltq_x_n_s8(int8x16_t a, mve_pred16_t p) @@ -1590,8 +1590,8 @@ int16x8_t test_vshlltq_x_n_s8(int8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_x_n_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 6, i32 0, i32 1, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 6, i32 0, i32 1, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vshlltq_x_n_s16(int16x8_t a, mve_pred16_t p) @@ -1606,8 +1606,8 @@ int32x4_t test_vshlltq_x_n_s16(int16x8_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_x_n_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 5, i32 1, i32 1, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.vshll.imm.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], i32 5, i32 1, i32 1, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vshlltq_x_n_u8(uint8x16_t a, mve_pred16_t p) @@ -1622,8 +1622,8 @@ uint16x8_t test_vshlltq_x_n_u8(uint8x16_t a, mve_pred16_t p) // CHECK-LABEL: @test_vshlltq_x_n_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 3, i32 1, i32 1, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vshll.imm.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], i32 3, i32 1, i32 1, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vshlltq_x_n_u16(uint16x8_t a, mve_pred16_t p) diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vhaddq.c b/clang/test/CodeGen/arm-mve-intrinsics/vhaddq.c index 1d97ea80520c1..cd61bc782c7dd 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vhaddq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vhaddq.c @@ -141,3 +141,159 @@ uint32x4_t test_vhaddq_x_u32(uint32x4_t a, uint32x4_t b, mve_pred16_t p) return vhaddq_x_u32(a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vhaddq_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.mve.vhadd.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vhaddq_n_u8(uint8x16_t a, uint8_t b) +{ +#ifdef POLYMORPHIC + return vhaddq(a, b); +#else /* POLYMORPHIC */ + return vhaddq_n_u8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vhadd.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vhaddq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vhaddq(a, b); +#else /* POLYMORPHIC */ + return vhaddq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vhadd.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vhaddq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vhaddq(a, b); +#else /* POLYMORPHIC */ + return vhaddq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.hadd.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 0, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vhaddq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_m_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.hadd.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vhaddq_m_n_u16(uint16x8_t inactive, uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_m_n_u16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.hadd.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vhaddq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_x_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.hadd.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 1, <16 x i1> [[TMP1]], <16 x i8> undef) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vhaddq_x_n_u8(uint8x16_t a, uint8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_x_n_u8(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_x_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.hadd.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0, <8 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vhaddq_x_n_s16(int16x8_t a, int16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_x_n_s16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhaddq_x_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.hadd.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1, <4 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +uint32x4_t test_vhaddq_x_n_u32(uint32x4_t a, uint32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhaddq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhaddq_x_n_u32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vhsubq.c b/clang/test/CodeGen/arm-mve-intrinsics/vhsubq.c index 633fd32d947fe..529936998b375 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vhsubq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vhsubq.c @@ -93,3 +93,159 @@ int32x4_t test_vhsubq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, mve_pr return vhsubq_m_s32(inactive, a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vhsubq_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.mve.vhsub.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vhsubq_n_u8(uint8x16_t a, uint8_t b) +{ +#ifdef POLYMORPHIC + return vhsubq(a, b); +#else /* POLYMORPHIC */ + return vhsubq_n_u8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vhsub.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vhsubq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vhsubq(a, b); +#else /* POLYMORPHIC */ + return vhsubq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vhsub.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vhsubq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vhsubq(a, b); +#else /* POLYMORPHIC */ + return vhsubq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.hsub.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 0, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vhsubq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_m_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.hsub.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vhsubq_m_n_u16(uint16x8_t inactive, uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_m_n_u16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.hsub.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vhsubq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_x_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.hsub.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 1, <16 x i1> [[TMP1]], <16 x i8> undef) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vhsubq_x_n_u8(uint8x16_t a, uint8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_x_n_u8(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_x_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.hsub.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0, <8 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vhsubq_x_n_s16(int16x8_t a, int16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_x_n_s16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vhsubq_x_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.hsub.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1, <4 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +uint32x4_t test_vhsubq_x_n_u32(uint32x4_t a, uint32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vhsubq_x(a, b, p); +#else /* POLYMORPHIC */ + return vhsubq_x_n_u32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmovl.c b/clang/test/CodeGen/arm-mve-intrinsics/vmovl.c new file mode 100644 index 0000000000000..0b8ef596faeda --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmovl.c @@ -0,0 +1,126 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vmovlbq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[TMP0]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP1]] +// +int16x8_t test_vmovlbq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vmovlbq(a); +#else /* POLYMORPHIC */ + return vmovlbq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovlbq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <4 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int32x4_t test_vmovlbq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vmovlbq(a); +#else /* POLYMORPHIC */ + return vmovlbq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovlbq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP1]] +// +uint16x8_t test_vmovlbq_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vmovlbq(a); +#else /* POLYMORPHIC */ + return vmovlbq_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovlbq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <4 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +uint32x4_t test_vmovlbq_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vmovlbq(a); +#else /* POLYMORPHIC */ + return vmovlbq_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovltq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[TMP0]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP1]] +// +int16x8_t test_vmovltq_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vmovltq(a); +#else /* POLYMORPHIC */ + return vmovltq_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovltq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <4 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int32x4_t test_vmovltq_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vmovltq(a); +#else /* POLYMORPHIC */ + return vmovltq_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovltq_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i16> +// CHECK-NEXT: ret <8 x i16> [[TMP1]] +// +uint16x8_t test_vmovltq_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vmovltq(a); +#else /* POLYMORPHIC */ + return vmovltq_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmovltq_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <4 x i32> +// CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +uint32x4_t test_vmovltq_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vmovltq(a); +#else /* POLYMORPHIC */ + return vmovltq_u16(a); +#endif /* POLYMORPHIC */ +} + diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmovn.c b/clang/test/CodeGen/arm-mve-intrinsics/vmovn.c new file mode 100644 index 0000000000000..5d157de0feb86 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmovn.c @@ -0,0 +1,199 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck --check-prefix=LE %s +// RUN: %clang_cc1 -triple thumbebv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck --check-prefix=BE %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck --check-prefix=LE %s +// RUN: %clang_cc1 -triple thumbebv8.1m.main-arm-none-eabi -target-feature +mve -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck --check-prefix=BE %s + +#include + +// LE-LABEL: @test_vmovnbq_s16( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// LE-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> +// LE-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[TMP1]], <16 x i32> +// LE-NEXT: [[TMP3:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8> +// LE-NEXT: ret <16 x i8> [[TMP3]] +// +// BE-LABEL: @test_vmovnbq_s16( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// BE-NEXT: [[TMP1:%.*]] = call <8 x i16> @llvm.arm.mve.vreinterpretq.v8i16.v16i8(<16 x i8> [[TMP0]]) +// BE-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[TMP1]], <16 x i32> +// BE-NEXT: [[TMP3:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8> +// BE-NEXT: ret <16 x i8> [[TMP3]] +// +int8x16_t test_vmovnbq_s16(int8x16_t a, int16x8_t b) +{ +#ifdef POLYMORPHIC + return vmovnbq(a, b); +#else /* POLYMORPHIC */ + return vmovnbq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovnbq_s32( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// LE-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[TMP0]] to <4 x i32> +// LE-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[B:%.*]], <4 x i32> [[TMP1]], <8 x i32> +// LE-NEXT: [[TMP3:%.*]] = trunc <8 x i32> [[TMP2]] to <8 x i16> +// LE-NEXT: ret <8 x i16> [[TMP3]] +// +// BE-LABEL: @test_vmovnbq_s32( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// BE-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vreinterpretq.v4i32.v8i16(<8 x i16> [[TMP0]]) +// BE-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[B:%.*]], <4 x i32> [[TMP1]], <8 x i32> +// BE-NEXT: [[TMP3:%.*]] = trunc <8 x i32> [[TMP2]] to <8 x i16> +// BE-NEXT: ret <8 x i16> [[TMP3]] +// +int16x8_t test_vmovnbq_s32(int16x8_t a, int32x4_t b) +{ +#ifdef POLYMORPHIC + return vmovnbq(a, b); +#else /* POLYMORPHIC */ + return vmovnbq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovnbq_u16( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// LE-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> +// LE-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[TMP1]], <16 x i32> +// LE-NEXT: [[TMP3:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8> +// LE-NEXT: ret <16 x i8> [[TMP3]] +// +// BE-LABEL: @test_vmovnbq_u16( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// BE-NEXT: [[TMP1:%.*]] = call <8 x i16> @llvm.arm.mve.vreinterpretq.v8i16.v16i8(<16 x i8> [[TMP0]]) +// BE-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> [[TMP1]], <16 x i32> +// BE-NEXT: [[TMP3:%.*]] = trunc <16 x i16> [[TMP2]] to <16 x i8> +// BE-NEXT: ret <16 x i8> [[TMP3]] +// +uint8x16_t test_vmovnbq_u16(uint8x16_t a, uint16x8_t b) +{ +#ifdef POLYMORPHIC + return vmovnbq(a, b); +#else /* POLYMORPHIC */ + return vmovnbq_u16(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovnbq_u32( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// LE-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[TMP0]] to <4 x i32> +// LE-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[B:%.*]], <4 x i32> [[TMP1]], <8 x i32> +// LE-NEXT: [[TMP3:%.*]] = trunc <8 x i32> [[TMP2]] to <8 x i16> +// LE-NEXT: ret <8 x i16> [[TMP3]] +// +// BE-LABEL: @test_vmovnbq_u32( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// BE-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.arm.mve.vreinterpretq.v4i32.v8i16(<8 x i16> [[TMP0]]) +// BE-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[B:%.*]], <4 x i32> [[TMP1]], <8 x i32> +// BE-NEXT: [[TMP3:%.*]] = trunc <8 x i32> [[TMP2]] to <8 x i16> +// BE-NEXT: ret <8 x i16> [[TMP3]] +// +uint16x8_t test_vmovnbq_u32(uint16x8_t a, uint32x4_t b) +{ +#ifdef POLYMORPHIC + return vmovnbq(a, b); +#else /* POLYMORPHIC */ + return vmovnbq_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovntq_s16( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = bitcast <16 x i8> [[A:%.*]] to <8 x i16> +// LE-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> [[B:%.*]], <16 x i32> +// LE-NEXT: [[TMP2:%.*]] = trunc <16 x i16> [[TMP1]] to <16 x i8> +// LE-NEXT: ret <16 x i8> [[TMP2]] +// +// BE-LABEL: @test_vmovntq_s16( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vreinterpretq.v8i16.v16i8(<16 x i8> [[A:%.*]]) +// BE-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> [[B:%.*]], <16 x i32> +// BE-NEXT: [[TMP2:%.*]] = trunc <16 x i16> [[TMP1]] to <16 x i8> +// BE-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vmovntq_s16(int8x16_t a, int16x8_t b) +{ +#ifdef POLYMORPHIC + return vmovntq(a, b); +#else /* POLYMORPHIC */ + return vmovntq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovntq_s32( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A:%.*]] to <4 x i32> +// LE-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> [[B:%.*]], <8 x i32> +// LE-NEXT: [[TMP2:%.*]] = trunc <8 x i32> [[TMP1]] to <8 x i16> +// LE-NEXT: ret <8 x i16> [[TMP2]] +// +// BE-LABEL: @test_vmovntq_s32( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vreinterpretq.v4i32.v8i16(<8 x i16> [[A:%.*]]) +// BE-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> [[B:%.*]], <8 x i32> +// BE-NEXT: [[TMP2:%.*]] = trunc <8 x i32> [[TMP1]] to <8 x i16> +// BE-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vmovntq_s32(int16x8_t a, int32x4_t b) +{ +#ifdef POLYMORPHIC + return vmovntq(a, b); +#else /* POLYMORPHIC */ + return vmovntq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovntq_u16( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = bitcast <16 x i8> [[A:%.*]] to <8 x i16> +// LE-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> [[B:%.*]], <16 x i32> +// LE-NEXT: [[TMP2:%.*]] = trunc <16 x i16> [[TMP1]] to <16 x i8> +// LE-NEXT: ret <16 x i8> [[TMP2]] +// +// BE-LABEL: @test_vmovntq_u16( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vreinterpretq.v8i16.v16i8(<16 x i8> [[A:%.*]]) +// BE-NEXT: [[TMP1:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> [[B:%.*]], <16 x i32> +// BE-NEXT: [[TMP2:%.*]] = trunc <16 x i16> [[TMP1]] to <16 x i8> +// BE-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vmovntq_u16(uint8x16_t a, uint16x8_t b) +{ +#ifdef POLYMORPHIC + return vmovntq(a, b); +#else /* POLYMORPHIC */ + return vmovntq_u16(a, b); +#endif /* POLYMORPHIC */ +} + +// LE-LABEL: @test_vmovntq_u32( +// LE-NEXT: entry: +// LE-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A:%.*]] to <4 x i32> +// LE-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> [[B:%.*]], <8 x i32> +// LE-NEXT: [[TMP2:%.*]] = trunc <8 x i32> [[TMP1]] to <8 x i16> +// LE-NEXT: ret <8 x i16> [[TMP2]] +// +// BE-LABEL: @test_vmovntq_u32( +// BE-NEXT: entry: +// BE-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vreinterpretq.v4i32.v8i16(<8 x i16> [[A:%.*]]) +// BE-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> [[B:%.*]], <8 x i32> +// BE-NEXT: [[TMP2:%.*]] = trunc <8 x i32> [[TMP1]] to <8 x i16> +// BE-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vmovntq_u32(uint16x8_t a, uint32x4_t b) +{ +#ifdef POLYMORPHIC + return vmovntq(a, b); +#else /* POLYMORPHIC */ + return vmovntq_u32(a, b); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmullbq.c b/clang/test/CodeGen/arm-mve-intrinsics/vmullbq.c index 757fb03b0bc53..2634d63019f91 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vmullbq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmullbq.c @@ -63,8 +63,8 @@ uint32x4_t test_vmullbq_poly_p16(uint16x8_t a, uint16x8_t b) // CHECK-LABEL: @test_vmullbq_int_m_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, i32 0, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, i32 0, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vmullbq_int_m_s8(int16x8_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p) @@ -79,8 +79,8 @@ int16x8_t test_vmullbq_int_m_s8(int16x8_t inactive, int8x16_t a, int8x16_t b, mv // CHECK-LABEL: @test_vmullbq_int_m_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1, i32 0, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1, i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vmullbq_int_m_u16(uint32x4_t inactive, uint16x8_t a, uint16x8_t b, mve_pred16_t p) @@ -111,8 +111,8 @@ int64x2_t test_vmullbq_int_m_s32(int64x2_t inactive, int32x4_t a, int32x4_t b, m // CHECK-LABEL: @test_vmullbq_poly_m_p8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vmullbq_poly_m_p8(uint16x8_t inactive, uint8x16_t a, uint8x16_t b, mve_pred16_t p) @@ -127,8 +127,8 @@ uint16x8_t test_vmullbq_poly_m_p8(uint16x8_t inactive, uint8x16_t a, uint8x16_t // CHECK-LABEL: @test_vmullbq_int_x_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, i32 0, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, i32 0, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vmullbq_int_x_u8(uint8x16_t a, uint8x16_t b, mve_pred16_t p) @@ -143,8 +143,8 @@ uint16x8_t test_vmullbq_int_x_u8(uint8x16_t a, uint8x16_t b, mve_pred16_t p) // CHECK-LABEL: @test_vmullbq_int_x_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, i32 0, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, i32 0, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vmullbq_int_x_s16(int16x8_t a, int16x8_t b, mve_pred16_t p) @@ -175,8 +175,8 @@ uint64x2_t test_vmullbq_int_x_u32(uint32x4_t a, uint32x4_t b, mve_pred16_t p) // CHECK-LABEL: @test_vmullbq_poly_x_p16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.poly.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.poly.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vmullbq_poly_x_p16(uint16x8_t a, uint16x8_t b, mve_pred16_t p) diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmulltq.c b/clang/test/CodeGen/arm-mve-intrinsics/vmulltq.c index 1cd982e31a4e0..a56d2e3d8c6c5 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vmulltq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmulltq.c @@ -63,8 +63,8 @@ uint32x4_t test_vmulltq_poly_p16(uint16x8_t a, uint16x8_t b) // CHECK-LABEL: @test_vmulltq_int_m_s8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, i32 1, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0, i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // int16x8_t test_vmulltq_int_m_s8(int16x8_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p) @@ -79,8 +79,8 @@ int16x8_t test_vmulltq_int_m_s8(int16x8_t inactive, int8x16_t a, int8x16_t b, mv // CHECK-LABEL: @test_vmulltq_int_m_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1, i32 1, <8 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1, i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // uint32x4_t test_vmulltq_int_m_u16(uint32x4_t inactive, uint16x8_t a, uint16x8_t b, mve_pred16_t p) @@ -111,8 +111,8 @@ int64x2_t test_vmulltq_int_m_s32(int64x2_t inactive, int32x4_t a, int32x4_t b, m // CHECK-LABEL: @test_vmulltq_poly_m_p8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, <16 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vmulltq_poly_m_p8(uint16x8_t inactive, uint8x16_t a, uint8x16_t b, mve_pred16_t p) @@ -127,8 +127,8 @@ uint16x8_t test_vmulltq_poly_m_p8(uint16x8_t inactive, uint8x16_t a, uint8x16_t // CHECK-LABEL: @test_vmulltq_int_x_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, i32 1, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.int.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, i32 1, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vmulltq_int_x_u8(uint8x16_t a, uint8x16_t b, mve_pred16_t p) @@ -143,8 +143,8 @@ uint16x8_t test_vmulltq_int_x_u8(uint8x16_t a, uint8x16_t b, mve_pred16_t p) // CHECK-LABEL: @test_vmulltq_int_x_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, i32 1, <8 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mull.int.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, i32 1, <4 x i1> [[TMP1]], <4 x i32> undef) // CHECK-NEXT: ret <4 x i32> [[TMP2]] // int32x4_t test_vmulltq_int_x_s16(int16x8_t a, int16x8_t b, mve_pred16_t p) @@ -175,8 +175,8 @@ uint64x2_t test_vmulltq_int_x_u32(uint32x4_t a, uint32x4_t b, mve_pred16_t p) // CHECK-LABEL: @test_vmulltq_poly_x_p8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 -// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, <16 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mull.poly.predicated.v8i16.v16i8.v8i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1, <8 x i1> [[TMP1]], <8 x i16> undef) // CHECK-NEXT: ret <8 x i16> [[TMP2]] // uint16x8_t test_vmulltq_poly_x_p8(uint8x16_t a, uint8x16_t b, mve_pred16_t p) diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmulq.c b/clang/test/CodeGen/arm-mve-intrinsics/vmulq.c index 536bc7322fc2a..3619dabb81e1d 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vmulq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmulq.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s #include @@ -172,14 +172,14 @@ uint32x4_t test_vmulq_x_u32(uint32x4_t a, uint32x4_t b, mve_pred16_t p) #endif /* POLYMORPHIC */ } -// CHECK-LABEL: @test_vmulq_m_f32( +// CHECK-LABEL: @test_vmulq_x_f32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.mul.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], <4 x i1> [[TMP1]], <4 x float> undef) // CHECK-NEXT: ret <4 x float> [[TMP2]] // -float32x4_t test_vmulq_m_f32(float32x4_t a, float32x4_t b, mve_pred16_t p) +float32x4_t test_vmulq_x_f32(float32x4_t a, float32x4_t b, mve_pred16_t p) { #ifdef POLYMORPHIC return vmulq_x(a, b, p); @@ -187,3 +187,213 @@ float32x4_t test_vmulq_m_f32(float32x4_t a, float32x4_t b, mve_pred16_t p) return vmulq_x_f32(a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vmulq_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = mul <16 x i8> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vmulq_n_u8(uint8x16_t a, uint8_t b) +{ +#ifdef POLYMORPHIC + return vmulq(a, b); +#else /* POLYMORPHIC */ + return vmulq_n_u8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = mul <8 x i16> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vmulq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vmulq(a, b); +#else /* POLYMORPHIC */ + return vmulq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = mul <4 x i32> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vmulq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vmulq(a, b); +#else /* POLYMORPHIC */ + return vmulq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_n_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> undef, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = fmul <4 x float> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vmulq_n_f32(float32x4_t a, float32_t b) +{ +#ifdef POLYMORPHIC + return vmulq(a, b); +#else /* POLYMORPHIC */ + return vmulq_n_f32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.mul.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vmulq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vmulq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_m_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mul.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vmulq_m_n_u16(uint16x8_t inactive, uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vmulq_m_n_u16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mul.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vmulq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vmulq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_m_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[B_COERCE:%.*]] to i32 +// CHECK-NEXT: [[TMP_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[TMP0]] to i16 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP_0_EXTRACT_TRUNC]] to half +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> undef, half [[TMP1]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP3:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP2]]) +// CHECK-NEXT: [[TMP4:%.*]] = call <8 x half> @llvm.arm.mve.mul.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[DOTSPLAT]], <8 x i1> [[TMP3]], <8 x half> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP4]] +// +float16x8_t test_vmulq_m_n_f16(float16x8_t inactive, float16x8_t a, float16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vmulq_m_n_f16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_x_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.mul.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> undef) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vmulq_x_n_u8(uint8x16_t a, uint8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_x(a, b, p); +#else /* POLYMORPHIC */ + return vmulq_x_n_u8(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_x_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.mul.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vmulq_x_n_s16(int16x8_t a, int16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_x(a, b, p); +#else /* POLYMORPHIC */ + return vmulq_x_n_s16(a, b, p); +#endif /* POLYMORPHIC */ +} +// CHECK-LABEL: @test_vmulq_x_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.mul.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x i32> undef) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +uint32x4_t test_vmulq_x_n_u32(uint32x4_t a, uint32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_x(a, b, p); +#else /* POLYMORPHIC */ + return vmulq_x_n_u32(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmulq_x_n_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> undef, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.mul.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x float> undef) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vmulq_x_n_f32(float32x4_t a, float32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmulq_x(a, b, p); +#else /* POLYMORPHIC */ + return vmulq_x_n_f32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqaddq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqaddq.c index 8361ab3618ed7..8ed34dd752f31 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vqaddq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqaddq.c @@ -93,3 +93,105 @@ int32x4_t test_vqaddq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, mve_pr return vqaddq_m_s32(inactive, a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vqaddq_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vqaddq_n_u8(uint8x16_t a, uint8_t b) +{ +#ifdef POLYMORPHIC + return vqaddq(a, b); +#else /* POLYMORPHIC */ + return vqaddq_n_u8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqaddq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vqaddq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vqaddq(a, b); +#else /* POLYMORPHIC */ + return vqaddq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqaddq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vqaddq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vqaddq(a, b); +#else /* POLYMORPHIC */ + return vqaddq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqaddq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.qadd.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 0, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vqaddq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqaddq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqaddq_m_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.qadd.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vqaddq_m_n_u16(uint16x8_t inactive, uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqaddq_m_n_u16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqaddq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.qadd.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqaddq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqaddq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqaddq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqdmulhq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqdmulhq.c index eb7e0a0afdf3c..bab911f385e78 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vqdmulhq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqdmulhq.c @@ -93,3 +93,105 @@ int32x4_t test_vqdmulhq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, mve_ return vqdmulhq_m_s32(inactive, a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vqdmulhq_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.mve.vqdmulh.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vqdmulhq_n_s8(int8x16_t a, int8_t b) +{ +#ifdef POLYMORPHIC + return vqdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqdmulhq_n_s8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulhq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vqdmulh.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vqdmulhq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vqdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqdmulhq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulhq_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmulh.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqdmulhq_n_s32(int32x4_t a, int32_t b) +{ +#ifdef POLYMORPHIC + return vqdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqdmulhq_n_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulhq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.qdmulh.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vqdmulhq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulhq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulhq_m_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.qdmulh.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vqdmulhq_m_n_s16(int16x8_t inactive, int16x8_t a, int16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulhq_m_n_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulhq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.qdmulh.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqdmulhq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulhq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqdmullbq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqdmullbq.c new file mode 100644 index 0000000000000..c7aa5a3c17b55 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqdmullbq.c @@ -0,0 +1,125 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vqdmullbq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.v4i32.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqdmullbq_s16(int16x8_t a, int16x8_t b) { +#ifdef POLYMORPHIC + return vqdmullbq(a, b); +#else /* POLYMORPHIC */ + return vqdmullbq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.v2i64.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0) +// CHECK-NEXT: ret <2 x i64> [[TMP0]] +// +int64x2_t test_vqdmullbq_s32(int32x4_t a, int32x4_t b) { +#ifdef POLYMORPHIC + return vqdmullbq(a, b); +#else /* POLYMORPHIC */ + return vqdmullbq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_m_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqdmullbq_m_s16(int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmullbq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmullbq_m_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_m_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 0, <4 x i1> [[TMP1]], <2 x i64> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <2 x i64> [[TMP2]] +// +int64x2_t test_vqdmullbq_m_s32(int64x2_t inactive, int32x4_t a, int32x4_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmullbq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmullbq_m_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.v4i32.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqdmullbq_n_s16(int16x8_t a, int16_t b) { +#ifdef POLYMORPHIC + return vqdmullbq(a, b); +#else /* POLYMORPHIC */ + return vqdmullbq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.v2i64.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0) +// CHECK-NEXT: ret <2 x i64> [[TMP0]] +// +int64x2_t test_vqdmullbq_n_s32(int32x4_t a, int32_t b) { +#ifdef POLYMORPHIC + return vqdmullbq(a, b); +#else /* POLYMORPHIC */ + return vqdmullbq_n_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_m_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqdmullbq_m_n_s16(int32x4_t inactive, int16x8_t a, int16_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmullbq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmullbq_m_n_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmullbq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <2 x i64> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <2 x i64> [[TMP2]] +// +int64x2_t test_vqdmullbq_m_n_s32(int64x2_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmullbq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmullbq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqdmulltq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqdmulltq.c new file mode 100644 index 0000000000000..0a03e2e963df2 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqdmulltq.c @@ -0,0 +1,125 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vqdmulltq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.v4i32.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqdmulltq_s16(int16x8_t a, int16x8_t b) { +#ifdef POLYMORPHIC + return vqdmulltq(a, b); +#else /* POLYMORPHIC */ + return vqdmulltq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.v2i64.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 1) +// CHECK-NEXT: ret <2 x i64> [[TMP0]] +// +int64x2_t test_vqdmulltq_s32(int32x4_t a, int32x4_t b) { +#ifdef POLYMORPHIC + return vqdmulltq(a, b); +#else /* POLYMORPHIC */ + return vqdmulltq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_m_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqdmulltq_m_s16(int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmulltq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulltq_m_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_m_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], i32 1, <4 x i1> [[TMP1]], <2 x i64> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <2 x i64> [[TMP2]] +// +int64x2_t test_vqdmulltq_m_s32(int64x2_t inactive, int32x4_t a, int32x4_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmulltq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulltq_m_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.v4i32.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqdmulltq_n_s16(int16x8_t a, int16_t b) { +#ifdef POLYMORPHIC + return vqdmulltq(a, b); +#else /* POLYMORPHIC */ + return vqdmulltq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.v2i64.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1) +// CHECK-NEXT: ret <2 x i64> [[TMP0]] +// +int64x2_t test_vqdmulltq_n_s32(int32x4_t a, int32_t b) { +#ifdef POLYMORPHIC + return vqdmulltq(a, b); +#else /* POLYMORPHIC */ + return vqdmulltq_n_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_m_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vqdmull.predicated.v4i32.v8i16.v4i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqdmulltq_m_n_s16(int32x4_t inactive, int16x8_t a, int16_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmulltq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulltq_m_n_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqdmulltq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 1, <4 x i1> [[TMP1]], <2 x i64> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <2 x i64> [[TMP2]] +// +int64x2_t test_vqdmulltq_m_n_s32(int64x2_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) { +#ifdef POLYMORPHIC + return vqdmulltq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqdmulltq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqrdmulhq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqrdmulhq.c index 27b7efd31014f..919074e7fddbe 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vqrdmulhq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqrdmulhq.c @@ -93,3 +93,105 @@ int32x4_t test_vqrdmulhq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, mve return vqrdmulhq_m_s32(inactive, a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vqrdmulhq_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.mve.vqrdmulh.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vqrdmulhq_n_s8(int8x16_t a, int8_t b) +{ +#ifdef POLYMORPHIC + return vqrdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqrdmulhq_n_s8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqrdmulhq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.arm.mve.vqrdmulh.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vqrdmulhq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vqrdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqrdmulhq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqrdmulhq_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vqrdmulh.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vqrdmulhq_n_s32(int32x4_t a, int32_t b) +{ +#ifdef POLYMORPHIC + return vqrdmulhq(a, b); +#else /* POLYMORPHIC */ + return vqrdmulhq_n_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqrdmulhq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.qrdmulh.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vqrdmulhq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqrdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqrdmulhq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqrdmulhq_m_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.qrdmulh.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +int16x8_t test_vqrdmulhq_m_n_s16(int16x8_t inactive, int16x8_t a, int16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqrdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqrdmulhq_m_n_s16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqrdmulhq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.qrdmulh.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqrdmulhq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqrdmulhq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqrdmulhq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vqsubq.c b/clang/test/CodeGen/arm-mve-intrinsics/vqsubq.c index c8924bf912800..28ced90ef0f71 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vqsubq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vqsubq.c @@ -93,3 +93,105 @@ int32x4_t test_vqsubq_m_s32(int32x4_t inactive, int32x4_t a, int32x4_t b, mve_pr return vqsubq_m_s32(inactive, a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vqsubq_n_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vqsubq_n_u8(uint8x16_t a, uint8_t b) +{ +#ifdef POLYMORPHIC + return vqsubq(a, b); +#else /* POLYMORPHIC */ + return vqsubq_n_u8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqsubq_n_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vqsubq_n_s16(int16x8_t a, int16_t b) +{ +#ifdef POLYMORPHIC + return vqsubq(a, b); +#else /* POLYMORPHIC */ + return vqsubq_n_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqsubq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vqsubq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vqsubq(a, b); +#else /* POLYMORPHIC */ + return vqsubq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqsubq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.qsub.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], i32 0, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vqsubq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqsubq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqsubq_m_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.qsub.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vqsubq_m_n_u16(uint16x8_t inactive, uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqsubq_m_n_u16(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vqsubq_m_n_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.qsub.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[DOTSPLAT]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +int32x4_t test_vqsubq_m_n_s32(int32x4_t inactive, int32x4_t a, int32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vqsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vqsubq_m_n_s32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vrev.c b/clang/test/CodeGen/arm-mve-intrinsics/vrev.c new file mode 100644 index 0000000000000..384d736d2a6db --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vrev.c @@ -0,0 +1,215 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg -sroa -early-cse | FileCheck %s + +#include + +// CHECK-LABEL: @test_vrev16q_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vrev16q_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev16q(a); +#else /* POLYMORPHIC */ + return vrev16q_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev16q_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vrev16q_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev16q(a); +#else /* POLYMORPHIC */ + return vrev16q_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev32q_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vrev32q_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev32q(a); +#else /* POLYMORPHIC */ + return vrev32q_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev32q_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vrev32q_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev32q(a); +#else /* POLYMORPHIC */ + return vrev32q_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev32q_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vrev32q_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev32q(a); +#else /* POLYMORPHIC */ + return vrev32q_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev32q_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +uint16x8_t test_vrev32q_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev32q(a); +#else /* POLYMORPHIC */ + return vrev32q_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev32q_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> undef, <8 x i32> +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrev32q_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev32q(a); +#else /* POLYMORPHIC */ + return vrev32q_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +int8x16_t test_vrev64q_s8(int8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_s8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <16 x i32> +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +uint8x16_t test_vrev64q_u8(uint8x16_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_u8(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +int16x8_t test_vrev64q_s16(int16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_s16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> undef, <8 x i32> +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +uint16x8_t test_vrev64q_u16(uint16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_u16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> undef, <8 x i32> +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrev64q_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> undef, <4 x i32> +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrev64q_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i32> [[A:%.*]], <4 x i32> undef, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +int32x4_t test_vrev64q_s32(int32x4_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_s32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrev64q_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i32> [[A:%.*]], <4 x i32> undef, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vrev64q_u32(uint32x4_t a) +{ +#ifdef POLYMORPHIC + return vrev64q(a); +#else /* POLYMORPHIC */ + return vrev64q_u32(a); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vrnd.c b/clang/test/CodeGen/arm-mve-intrinsics/vrnd.c new file mode 100644 index 0000000000000..a324c36ed8382 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vrnd.c @@ -0,0 +1,173 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg -sroa -early-cse | FileCheck %s + +#include + +// CHECK-LABEL: @test_vrndaq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.round.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndaq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndaq(a); +#else /* POLYMORPHIC */ + return vrndaq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndaq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndaq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndaq(a); +#else /* POLYMORPHIC */ + return vrndaq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndmq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.floor.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndmq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndmq(a); +#else /* POLYMORPHIC */ + return vrndmq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndmq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndmq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndmq(a); +#else /* POLYMORPHIC */ + return vrndmq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndpq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.ceil.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndpq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndpq(a); +#else /* POLYMORPHIC */ + return vrndpq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndpq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndpq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndpq(a); +#else /* POLYMORPHIC */ + return vrndpq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.trunc.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndq(a); +#else /* POLYMORPHIC */ + return vrndq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndq(a); +#else /* POLYMORPHIC */ + return vrndq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndxq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.rint.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndxq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndxq(a); +#else /* POLYMORPHIC */ + return vrndxq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndxq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndxq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndxq(a); +#else /* POLYMORPHIC */ + return vrndxq_f32(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndnq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <8 x half> @llvm.arm.mve.vrintn.v8f16(<8 x half> [[A:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +float16x8_t test_vrndnq_f16(float16x8_t a) +{ +#ifdef POLYMORPHIC + return vrndnq(a); +#else /* POLYMORPHIC */ + return vrndnq_f16(a); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vrndnq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = call <4 x float> @llvm.arm.mve.vrintn.v4f32(<4 x float> [[A:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float32x4_t test_vrndnq_f32(float32x4_t a) +{ +#ifdef POLYMORPHIC + return vrndnq(a); +#else /* POLYMORPHIC */ + return vrndnq_f32(a); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vsubq.c b/clang/test/CodeGen/arm-mve-intrinsics/vsubq.c index dd11aa848bcc0..7231ae966306a 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/vsubq.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/vsubq.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s -// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -sroa | FileCheck %s #include @@ -95,3 +95,113 @@ float16x8_t test_vsubq_x_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) return vsubq_x_f16(a, b, p); #endif /* POLYMORPHIC */ } + +// CHECK-LABEL: @test_vsubq_n_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> undef, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = sub <4 x i32> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +uint32x4_t test_vsubq_n_u32(uint32x4_t a, uint32_t b) +{ +#ifdef POLYMORPHIC + return vsubq(a, b); +#else /* POLYMORPHIC */ + return vsubq_n_u32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vsubq_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[B_COERCE:%.*]] to i32 +// CHECK-NEXT: [[TMP_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[TMP0]] to i16 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP_0_EXTRACT_TRUNC]] to half +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> undef, half [[TMP1]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = fsub <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: ret <8 x half> [[TMP2]] +// +float16x8_t test_vsubq_n_f16(float16x8_t a, float16_t b) +{ +#ifdef POLYMORPHIC + return vsubq(a, b); +#else /* POLYMORPHIC */ + return vsubq_n_f16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vsubq_m_n_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <16 x i8> undef, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <16 x i8> [[DOTSPLATINSERT]], <16 x i8> undef, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.sub.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[DOTSPLAT]], <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +int8x16_t test_vsubq_m_n_s8(int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vsubq_m_n_s8(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vsubq_m_n_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> undef, float [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> undef, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.sub.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[DOTSPLAT]], <4 x i1> [[TMP1]], <4 x float> [[INACTIVE:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vsubq_m_n_f32(float32x4_t inactive, float32x4_t a, float32_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vsubq_m(inactive, a, b, p); +#else /* POLYMORPHIC */ + return vsubq_m_n_f32(inactive, a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vsubq_x_n_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x i16> undef, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x i16> [[DOTSPLATINSERT]], <8 x i16> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.sub.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[DOTSPLAT]], <8 x i1> [[TMP1]], <8 x i16> undef) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vsubq_x_n_u16(uint16x8_t a, uint16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vsubq_x(a, b, p); +#else /* POLYMORPHIC */ + return vsubq_x_n_u16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vsubq_x_n_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[B_COERCE:%.*]] to i32 +// CHECK-NEXT: [[TMP_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[TMP0]] to i16 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[TMP_0_EXTRACT_TRUNC]] to half +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> undef, half [[TMP1]], i32 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> undef, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP3:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP2]]) +// CHECK-NEXT: [[TMP4:%.*]] = call <8 x half> @llvm.arm.mve.sub.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[DOTSPLAT]], <8 x i1> [[TMP3]], <8 x half> undef) +// CHECK-NEXT: ret <8 x half> [[TMP4]] +// +float16x8_t test_vsubq_x_n_f16(float16x8_t a, float16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vsubq_x(a, b, p); +#else /* POLYMORPHIC */ + return vsubq_x_n_f16(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/asm-goto.c b/clang/test/CodeGen/asm-goto.c index 7692fbc6797b5..c322d4560f5af 100644 --- a/clang/test/CodeGen/asm-goto.c +++ b/clang/test/CodeGen/asm-goto.c @@ -2,19 +2,104 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple i386-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s -int foo(int cond) -{ +int test1(int cond) { + // CHECK-LABEL: define i32 @test1( // CHECK: callbr void asm sideeffect // CHECK: to label %asm.fallthrough [label %label_true, label %loop] - // CHECK: asm.fallthrough: - asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); + // CHECK-LABEL: asm.fallthrough: asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); + asm volatile goto("testl %0, %0; jne %l2;" :: "r"(cond)::label_true, loop); // CHECK: callbr void asm sideeffect // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop] - // CHECK: asm.fallthrough1: + // CHECK-LABEL: asm.fallthrough1: + return 0; +loop: + return 0; +label_true: + return 1; +} + +int test2(int cond) { + // CHECK-LABEL: define i32 @test2( + // CHECK: callbr i32 asm sideeffect + // CHECK: to label %asm.fallthrough [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough: + asm volatile goto("testl %0, %0; jne %l2;" : "=r"(cond) : "r"(cond) :: label_true, loop); + asm volatile goto("testl %0, %0; jne %l3;" : "=r"(cond) : "r"(cond) :: label_true, loop); + // CHECK: callbr i32 asm sideeffect + // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough1: + return 0; +loop: + return 0; +label_true: + return 1; +} + +int test3(int out1, int out2) { + // CHECK-LABEL: define i32 @test3( + // CHECK: callbr { i32, i32 } asm sideeffect + // CHECK: to label %asm.fallthrough [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough: + asm volatile goto("testl %0, %0; jne %l3;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); + asm volatile goto("testl %0, %0; jne %l4;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); + // CHECK: callbr { i32, i32 } asm sideeffect + // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough2: return 0; loop: return 0; label_true: return 1; } + +int test4(int out1, int out2) { + // CHECK-LABEL: define i32 @test4( + // CHECK: callbr { i32, i32 } asm sideeffect "jne ${3:l}", "={si},={di},r,X,X,0,1 + // CHECK: to label %asm.fallthrough [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough: + if (out1 < out2) + asm volatile goto("jne %l3" : "+S"(out1), "+D"(out2) : "r"(out1) :: label_true, loop); + else + asm volatile goto("jne %l5" : "+S"(out1), "+D"(out2) : "r"(out1), "r"(out2) :: label_true, loop); + // CHECK: callbr { i32, i32 } asm sideeffect "jne ${5:l}", "={si},={di},r,r,X,X,0,1 + // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop] + // CHECK-LABEL: asm.fallthrough2: + return out1 + out2; +loop: + return -1; +label_true: + return -2; +} + +int test5(int addr, int size, int limit) { + // CHECK-LABEL: define i32 @test5( + // CHECK: callbr i32 asm "add $1,$0 ; jc ${3:l} ; cmp $2,$0 ; ja ${3:l} ; ", "=r,imr,imr,X,0 + // CHECK: to label %asm.fallthrough [label %t_err] + // CHECK-LABEL: asm.fallthrough: + asm goto( + "add %1,%0 ; " + "jc %l[t_err] ; " + "cmp %2,%0 ; " + "ja %l[t_err] ; " + : "+r" (addr) + : "g" (size), "g" (limit) + : : t_err); + return 0; +t_err: + return 1; +} + +int test6(int out1) { + // CHECK-LABEL: define i32 @test6( + // CHECK: callbr i32 asm sideeffect "testl $0, $0; testl $1, $1; jne ${2:l}", "={si},r,X,X,0,{{.*}} i8* blockaddress(@test6, %label_true), i8* blockaddress(@test6, %landing) + // CHECK: to label %asm.fallthrough [label %label_true, label %landing] + // CHECK-LABEL: asm.fallthrough: + // CHECK-LABEL: landing: + int out2 = 42; + asm volatile goto("testl %0, %0; testl %1, %1; jne %l2" : "+S"(out2) : "r"(out1) :: label_true, landing); +landing: + return out1 + out2; +label_true: + return -2; +} diff --git a/clang/test/CodeGen/atomic_ops.c b/clang/test/CodeGen/atomic_ops.c index a853ba9f739c7..c1eb1d005dba9 100644 --- a/clang/test/CodeGen/atomic_ops.c +++ b/clang/test/CodeGen/atomic_ops.c @@ -1,7 +1,7 @@ -// XFAIL: hexagon,sparc -// (due to not having native load atomic support) -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple mips-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s \ +// RUN: -o - | FileCheck -check-prefixes=CHECK,NATIVE %s +// RUN: %clang_cc1 -triple riscv32 -target-feature -a -emit-llvm %s \ +// RUN: -o - | FileCheck -check-prefixes=CHECK,LIBCALL %s void foo(int x) { @@ -9,32 +9,47 @@ void foo(int x) _Atomic(short) j = 0; // Check that multiply / divides on atomics produce a cmpxchg loop i *= 2; - // CHECK: mul nsw i32 - // CHECK: {{(cmpxchg i32*|i1 @__atomic_compare_exchange\(i32 4,)}} + // NATIVE: mul nsw i32 + // NATIVE: cmpxchg i32* + // LIBCALL: mul nsw i32 + // LIBCALL: i1 @__atomic_compare_exchange(i32 4, i /= 2; - // CHECK: sdiv i32 - // CHECK: {{(cmpxchg i32*|i1 @__atomic_compare_exchange\(i32 4, )}} + // NATIVE: sdiv i32 + // NATIVE: cmpxchg i32* + // LIBCALL: sdiv i32 + // LIBCALL: i1 @__atomic_compare_exchange(i32 4, j /= x; - // CHECK: sdiv i32 - // CHECK: {{(cmpxchg i16*|i1 @__atomic_compare_exchange\(i32 2, )}} + // NATIVE: sdiv i32 + // NATIVE: cmpxchg i16* + // LIBCALL: sdiv i32 + // LIBCALL: i1 @__atomic_compare_exchange(i32 2, } extern _Atomic _Bool b; _Bool bar() { -// CHECK-LABEL: @bar -// CHECK: %[[load:.*]] = load atomic i8, i8* @b seq_cst -// CHECK: %[[tobool:.*]] = trunc i8 %[[load]] to i1 -// CHECK: ret i1 %[[tobool]] +// NATIVE-LABEL: @bar +// NATIVE: %[[load:.*]] = load atomic i8, i8* @b seq_cst +// NATIVE: %[[tobool:.*]] = trunc i8 %[[load]] to i1 +// NATIVE: ret i1 %[[tobool]] +// LIBCALL-LABEL: @bar +// LIBCALL: call void @__atomic_load(i32 1, i8* @b, i8* %atomic-temp, i32 5) +// LIBCALL: %[[load:.*]] = load i8, i8* %atomic-temp +// LIBCALL: %[[tobool:.*]] = trunc i8 %[[load]] to i1 +// LIBCALL: ret i1 %[[tobool]] + return b; } extern _Atomic(_Complex int) x; void baz(int y) { -// CHECK-LABEL: @baz -// CHECK: {{store atomic|call void @__atomic_store}} +// NATIVE-LABEL: @baz +// NATIVE: store atomic +// LIBCALL-LABEL: @baz +// LIBCALL: call void @__atomic_store + x += y; } @@ -84,9 +99,11 @@ _Atomic(int) compound_and(_Atomic(int) in) { } _Atomic(int) compound_mul(_Atomic(int) in) { -// CHECK-LABEL: @compound_mul -// CHECK: cmpxchg i32* {{%.*}}, i32 {{%.*}}, i32 [[NEW:%.*]] seq_cst seq_cst -// CHECK: ret i32 [[NEW]] +// NATIVE-LABEL: @compound_mul +// NATIVE: cmpxchg i32* {{%.*}}, i32 {{%.*}}, i32 [[NEW:%.*]] seq_cst seq_cst +// NATIVE: ret i32 [[NEW]] +// LIBCALL-LABEL: @compound_mul +// LIBCALL: i1 @__atomic_compare_exchange(i32 4, return (in *= 5); } diff --git a/clang/test/CodeGen/avx512f-builtins.c b/clang/test/CodeGen/avx512f-builtins.c index 9296108f01b10..bd15424af8891 100644 --- a/clang/test/CodeGen/avx512f-builtins.c +++ b/clang/test/CodeGen/avx512f-builtins.c @@ -887,38 +887,30 @@ __m512d test_mm512_maskz_fmsubadd_round_pd(__mmask8 __U, __m512d __A, __m512d __ } __m512d test_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}, i32 4) return _mm512_fmaddsub_pd(__A, __B, __C); } __m512d test_mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_mask_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}, i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_fmaddsub_pd(__A, __U, __B, __C); } __m512d test_mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm512_mask3_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}, i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask3_fmaddsub_pd(__A, __B, __C, __U); } __m512d test_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_maskz_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}, i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmaddsub_pd(__U, __A, __B, __C); @@ -926,17 +918,13 @@ __m512d test_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m __m512d test_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]], i32 4) return _mm512_fmsubadd_pd(__A, __B, __C); } __m512d test_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_mask_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]], i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_fmsubadd_pd(__A, __U, __B, __C); @@ -944,9 +932,7 @@ __m512d test_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m5 __m512d test_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_maskz_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]], i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsubadd_pd(__U, __A, __B, __C); @@ -1001,38 +987,30 @@ __m512 test_mm512_maskz_fmsubadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, } __m512 test_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> + // CHECK-NOT: fneg + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}, i32 4) return _mm512_fmaddsub_ps(__A, __B, __C); } __m512 test_mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_mask_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> + // CHECK-NOT: fneg + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}, i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_fmaddsub_ps(__A, __U, __B, __C); } __m512 test_mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { // CHECK-LABEL: @test_mm512_mask3_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> + // CHECK-NOT: fneg + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}, i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask3_fmaddsub_ps(__A, __B, __C, __U); } __m512 test_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_maskz_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> + // CHECK-NOT: fneg + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}, i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmaddsub_ps(__U, __A, __B, __C); @@ -1040,17 +1018,13 @@ __m512 test_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m51 __m512 test_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]], i32 4) return _mm512_fmsubadd_ps(__A, __B, __C); } __m512 test_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_mask_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]], i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_fmsubadd_ps(__A, __U, __B, __C); @@ -1058,9 +1032,7 @@ __m512 test_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __m512 test_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_maskz_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]], i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsubadd_ps(__U, __A, __B, __C); @@ -1108,9 +1080,7 @@ __m512d test_mm512_mask3_fmsubadd_round_pd(__m512d __A, __m512d __B, __m512d __C __m512d test_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm512_mask3_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <8 x double> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> + // CHECK: call <8 x double> @llvm.x86.avx512.vfmaddsub.pd.512(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]], i32 4) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask3_fmsubadd_pd(__A, __B, __C, __U); @@ -1126,9 +1096,7 @@ __m512 test_mm512_mask3_fmsubadd_round_ps(__m512 __A, __m512 __B, __m512 __C, __ __m512 test_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { // CHECK-LABEL: @test_mm512_mask3_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <16 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> + // CHECK: call <16 x float> @llvm.x86.avx512.vfmaddsub.ps.512(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]], i32 4) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask3_fmsubadd_ps(__A, __B, __C, __U); diff --git a/clang/test/CodeGen/avx512vl-builtins.c b/clang/test/CodeGen/avx512vl-builtins.c index 99c7dc61e448c..5bed16ec13278 100644 --- a/clang/test/CodeGen/avx512vl-builtins.c +++ b/clang/test/CodeGen/avx512vl-builtins.c @@ -3140,10 +3140,8 @@ __m256 test_mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 _ __m128d test_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_mask_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // CHECK-NOT: fneg + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3152,10 +3150,8 @@ __m128d test_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __m128d test_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_mask_fmsubadd_pd - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.*}} + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3164,10 +3160,8 @@ __m128d test_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __m128d test_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // CHECK-NOT: fneg + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3176,10 +3170,8 @@ __m128d test_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask __m128d test_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_maskz_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // CHECK-NOT: fneg + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3188,10 +3180,8 @@ __m128d test_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128 __m128d test_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_maskz_fmsubadd_pd - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.*}} + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3200,10 +3190,8 @@ __m128d test_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128 __m256d test_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_mask_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3212,10 +3200,8 @@ __m256d test_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m2 __m256d test_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_mask_fmsubadd_pd - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.*}} + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3224,10 +3210,8 @@ __m256d test_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m2 __m256d test_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3236,10 +3220,8 @@ __m256d test_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mm __m256d test_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_maskz_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3248,10 +3230,8 @@ __m256d test_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m __m256d test_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_maskz_fmsubadd_pd - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.*}} + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3260,10 +3240,8 @@ __m256d test_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m __m128 test_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_mask_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3272,10 +3250,8 @@ __m128 test_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C __m128 test_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_mask_fmsubadd_ps - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.*}} + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3284,10 +3260,8 @@ __m128 test_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C __m128 test_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3296,10 +3270,8 @@ __m128 test_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __ __m128 test_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_maskz_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3308,10 +3280,8 @@ __m128 test_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __ __m128 test_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_maskz_fmsubadd_ps - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.*}} + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3320,10 +3290,8 @@ __m128 test_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __ __m256 test_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_mask_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_fmaddsub_ps(__A, __U, __B, __C); @@ -3332,9 +3300,7 @@ __m256 test_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __m256 test_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_mask_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_fmsubadd_ps(__A, __U, __B, __C); @@ -3342,10 +3308,8 @@ __m256 test_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __m256 test_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask3_fmaddsub_ps(__A, __B, __C, __U); @@ -3353,10 +3317,8 @@ __m256 test_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __m256 test_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_maskz_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_fmaddsub_ps(__U, __A, __B, __C); @@ -3365,9 +3327,7 @@ __m256 test_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __m256 test_mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_maskz_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_fmsubadd_ps(__U, __A, __B, __C); @@ -3415,9 +3375,7 @@ __m256 test_mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __ __m128d test_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3427,9 +3385,7 @@ __m128d test_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask __m256d test_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3439,9 +3395,7 @@ __m256d test_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mm __m128 test_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3451,9 +3405,7 @@ __m128 test_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __ __m256 test_mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask3_fmsubadd_ps(__A, __B, __C, __U); diff --git a/clang/test/CodeGen/builtins-hexagon-v66-128B.c b/clang/test/CodeGen/builtins-hexagon-v66-128B.c index a1c4786cf24ce..074728ec07ec1 100644 --- a/clang/test/CodeGen/builtins-hexagon-v66-128B.c +++ b/clang/test/CodeGen/builtins-hexagon-v66-128B.c @@ -9,7 +9,7 @@ typedef long HEXAGON_Vect2048 __attribute__((__vector_size__(256))) __attribute__((aligned(256))); // CHECK-LABEL: @test1 -// CHECK: call <32 x i32> @llvm.hexagon.V6.vaddcarrysat.128B(<32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}}, <1024 x i1> %{{[0-9]+}}) +// CHECK: call <32 x i32> @llvm.hexagon.V6.vaddcarrysat.128B(<32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}}, <128 x i1> %{{[0-9]+}}) HEXAGON_Vect1024 test1(void *in, void *out) { HEXAGON_Vect1024 v1, v2; HEXAGON_Vect1024 *p; diff --git a/clang/test/CodeGen/builtins-hexagon-v66.c b/clang/test/CodeGen/builtins-hexagon-v66.c index 1382f18b4faf0..767f9faf77023 100644 --- a/clang/test/CodeGen/builtins-hexagon-v66.c +++ b/clang/test/CodeGen/builtins-hexagon-v66.c @@ -33,7 +33,7 @@ typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128))) __attribute__((aligned(128))); // CHECK-LABEL: @test5 -// CHECK: call <16 x i32> @llvm.hexagon.V6.vaddcarrysat(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}, <512 x i1> %{{[0-9]+}}) +// CHECK: call <16 x i32> @llvm.hexagon.V6.vaddcarrysat(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}, <64 x i1> %{{[0-9]+}}) HEXAGON_Vect512 test5(void *in, void *out) { HEXAGON_Vect512 v1, v2; HEXAGON_Vect512 *p; diff --git a/clang/test/CodeGen/builtins-hvx128.c b/clang/test/CodeGen/builtins-hvx128.c index 07d0e050ddc08..d61afdefc2ae3 100644 --- a/clang/test/CodeGen/builtins-hvx128.c +++ b/clang/test/CodeGen/builtins-hvx128.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128b -emit-llvm %s -o - | FileCheck %s void test() { + int q128 __attribute__((__vector_size__(128))); int v128 __attribute__((__vector_size__(128))); int v256 __attribute__((__vector_size__(256))); @@ -18,33 +19,33 @@ void test() { // CHECK: @llvm.hexagon.V6.lvsplatw.128B __builtin_HEXAGON_V6_lvsplatw_128B(0); // CHECK: @llvm.hexagon.V6.pred.and.128B - __builtin_HEXAGON_V6_pred_and_128B(v128, v128); + __builtin_HEXAGON_V6_pred_and_128B(q128, q128); // CHECK: @llvm.hexagon.V6.pred.and.n.128B - __builtin_HEXAGON_V6_pred_and_n_128B(v128, v128); + __builtin_HEXAGON_V6_pred_and_n_128B(q128, q128); // CHECK: @llvm.hexagon.V6.pred.not.128B - __builtin_HEXAGON_V6_pred_not_128B(v128); + __builtin_HEXAGON_V6_pred_not_128B(q128); // CHECK: @llvm.hexagon.V6.pred.or.128B - __builtin_HEXAGON_V6_pred_or_128B(v128, v128); + __builtin_HEXAGON_V6_pred_or_128B(q128, q128); // CHECK: @llvm.hexagon.V6.pred.or.n.128B - __builtin_HEXAGON_V6_pred_or_n_128B(v128, v128); + __builtin_HEXAGON_V6_pred_or_n_128B(q128, q128); // CHECK: @llvm.hexagon.V6.pred.scalar2.128B __builtin_HEXAGON_V6_pred_scalar2_128B(0); // CHECK: @llvm.hexagon.V6.pred.scalar2v2.128B __builtin_HEXAGON_V6_pred_scalar2v2_128B(0); // CHECK: @llvm.hexagon.V6.pred.xor.128B - __builtin_HEXAGON_V6_pred_xor_128B(v128, v128); + __builtin_HEXAGON_V6_pred_xor_128B(q128, q128); // CHECK: @llvm.hexagon.V6.shuffeqh.128B - __builtin_HEXAGON_V6_shuffeqh_128B(v128, v128); + __builtin_HEXAGON_V6_shuffeqh_128B(q128, q128); // CHECK: @llvm.hexagon.V6.shuffeqw.128B - __builtin_HEXAGON_V6_shuffeqw_128B(v128, v128); + __builtin_HEXAGON_V6_shuffeqw_128B(q128, q128); // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai.128B - __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vabsb.128B __builtin_HEXAGON_V6_vabsb_128B(v128); // CHECK: @llvm.hexagon.V6.vabsb.sat.128B @@ -70,9 +71,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddb.dv.128B __builtin_HEXAGON_V6_vaddb_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vaddbnq.128B - __builtin_HEXAGON_V6_vaddbnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddbnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddbq.128B - __builtin_HEXAGON_V6_vaddbq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddbq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddbsat.128B __builtin_HEXAGON_V6_vaddbsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vaddbsat.dv.128B @@ -88,9 +89,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddh.dv.128B __builtin_HEXAGON_V6_vaddh_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vaddhnq.128B - __builtin_HEXAGON_V6_vaddhnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddhnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddhq.128B - __builtin_HEXAGON_V6_vaddhq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddhq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddhsat.128B __builtin_HEXAGON_V6_vaddhsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vaddhsat.dv.128B @@ -126,9 +127,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddw.dv.128B __builtin_HEXAGON_V6_vaddw_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vaddwnq.128B - __builtin_HEXAGON_V6_vaddwnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddwnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddwq.128B - __builtin_HEXAGON_V6_vaddwq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vaddwq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vaddwsat.128B __builtin_HEXAGON_V6_vaddwsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vaddwsat.dv.128B @@ -140,21 +141,21 @@ void test() { // CHECK: @llvm.hexagon.V6.vand.128B __builtin_HEXAGON_V6_vand_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vandnqrt.128B - __builtin_HEXAGON_V6_vandnqrt_128B(v128, 0); + __builtin_HEXAGON_V6_vandnqrt_128B(q128, 0); // CHECK: @llvm.hexagon.V6.vandnqrt.acc.128B - __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, v128, 0); + __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, q128, 0); // CHECK: @llvm.hexagon.V6.vandqrt.128B - __builtin_HEXAGON_V6_vandqrt_128B(v128, 0); + __builtin_HEXAGON_V6_vandqrt_128B(q128, 0); // CHECK: @llvm.hexagon.V6.vandqrt.acc.128B - __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, v128, 0); + __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, q128, 0); // CHECK: @llvm.hexagon.V6.vandvnqv.128B - __builtin_HEXAGON_V6_vandvnqv_128B(v128, v128); + __builtin_HEXAGON_V6_vandvnqv_128B(q128, v128); // CHECK: @llvm.hexagon.V6.vandvqv.128B - __builtin_HEXAGON_V6_vandvqv_128B(v128, v128); + __builtin_HEXAGON_V6_vandvqv_128B(q128, v128); // CHECK: @llvm.hexagon.V6.vandvrt.128B __builtin_HEXAGON_V6_vandvrt_128B(v128, 0); // CHECK: @llvm.hexagon.V6.vandvrt.acc.128B - __builtin_HEXAGON_V6_vandvrt_acc_128B(v128, v128, 0); + __builtin_HEXAGON_V6_vandvrt_acc_128B(q128, v128, 0); // CHECK: @llvm.hexagon.V6.vaslh.128B __builtin_HEXAGON_V6_vaslh_128B(v128, 0); // CHECK: @llvm.hexagon.V6.vaslh.acc.128B @@ -296,87 +297,87 @@ void test() { // CHECK: @llvm.hexagon.V6.veqb.128B __builtin_HEXAGON_V6_veqb_128B(v128, v128); // CHECK: @llvm.hexagon.V6.veqb.and.128B - __builtin_HEXAGON_V6_veqb_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqb_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqb.or.128B - __builtin_HEXAGON_V6_veqb_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqb_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqb.xor.128B - __builtin_HEXAGON_V6_veqb_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqb_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqh.128B __builtin_HEXAGON_V6_veqh_128B(v128, v128); // CHECK: @llvm.hexagon.V6.veqh.and.128B - __builtin_HEXAGON_V6_veqh_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqh_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqh.or.128B - __builtin_HEXAGON_V6_veqh_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqh_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqh.xor.128B - __builtin_HEXAGON_V6_veqh_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqh_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqw.128B __builtin_HEXAGON_V6_veqw_128B(v128, v128); // CHECK: @llvm.hexagon.V6.veqw.and.128B - __builtin_HEXAGON_V6_veqw_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqw_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqw.or.128B - __builtin_HEXAGON_V6_veqw_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqw_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.veqw.xor.128B - __builtin_HEXAGON_V6_veqw_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_veqw_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgathermh.128B __builtin_HEXAGON_V6_vgathermh_128B(0, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgathermhq.128B - __builtin_HEXAGON_V6_vgathermhq_128B(0, v128, 0, 0, v128); + __builtin_HEXAGON_V6_vgathermhq_128B(0, q128, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgathermhw.128B __builtin_HEXAGON_V6_vgathermhw_128B(0, 0, 0, v256); // CHECK: @llvm.hexagon.V6.vgathermhwq.128B - __builtin_HEXAGON_V6_vgathermhwq_128B(0, v128, 0, 0, v256); + __builtin_HEXAGON_V6_vgathermhwq_128B(0, q128, 0, 0, v256); // CHECK: @llvm.hexagon.V6.vgathermw.128B __builtin_HEXAGON_V6_vgathermw_128B(0, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgathermwq.128B - __builtin_HEXAGON_V6_vgathermwq_128B(0, v128, 0, 0, v128); + __builtin_HEXAGON_V6_vgathermwq_128B(0, q128, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgtb.128B __builtin_HEXAGON_V6_vgtb_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgtb.and.128B - __builtin_HEXAGON_V6_vgtb_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtb_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtb.or.128B - __builtin_HEXAGON_V6_vgtb_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtb_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtb.xor.128B - __builtin_HEXAGON_V6_vgtb_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtb_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgth.128B __builtin_HEXAGON_V6_vgth_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgth.and.128B - __builtin_HEXAGON_V6_vgth_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgth_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgth.or.128B - __builtin_HEXAGON_V6_vgth_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgth_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgth.xor.128B - __builtin_HEXAGON_V6_vgth_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgth_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtub.128B __builtin_HEXAGON_V6_vgtub_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgtub.and.128B - __builtin_HEXAGON_V6_vgtub_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtub_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtub.or.128B - __builtin_HEXAGON_V6_vgtub_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtub_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtub.xor.128B - __builtin_HEXAGON_V6_vgtub_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtub_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuh.128B __builtin_HEXAGON_V6_vgtuh_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgtuh.and.128B - __builtin_HEXAGON_V6_vgtuh_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuh_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuh.or.128B - __builtin_HEXAGON_V6_vgtuh_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuh_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuh.xor.128B - __builtin_HEXAGON_V6_vgtuh_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuh_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuw.128B __builtin_HEXAGON_V6_vgtuw_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgtuw.and.128B - __builtin_HEXAGON_V6_vgtuw_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuw_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuw.or.128B - __builtin_HEXAGON_V6_vgtuw_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuw_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtuw.xor.128B - __builtin_HEXAGON_V6_vgtuw_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtuw_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtw.128B __builtin_HEXAGON_V6_vgtw_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vgtw.and.128B - __builtin_HEXAGON_V6_vgtw_and_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtw_and_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtw.or.128B - __builtin_HEXAGON_V6_vgtw_or_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtw_or_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vgtw.xor.128B - __builtin_HEXAGON_V6_vgtw_xor_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vgtw_xor_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vinsertwr.128B __builtin_HEXAGON_V6_vinsertwr_128B(v128, 0); // CHECK: @llvm.hexagon.V6.vlalignb.128B @@ -416,13 +417,13 @@ void test() { // CHECK: @llvm.hexagon.V6.vlutvwhi.128B __builtin_HEXAGON_V6_vlutvwhi_128B(v128, v128, 0); // CHECK: @llvm.hexagon.V6.vmaskedstorenq.128B - __builtin_HEXAGON_V6_vmaskedstorenq_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vmaskedstorenq_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vmaskedstorentnq.128B - __builtin_HEXAGON_V6_vmaskedstorentnq_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vmaskedstorentnq_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vmaskedstorentq.128B - __builtin_HEXAGON_V6_vmaskedstorentq_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vmaskedstorentq_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vmaskedstoreq.128B - __builtin_HEXAGON_V6_vmaskedstoreq_128B(v128, 0, v128); + __builtin_HEXAGON_V6_vmaskedstoreq_128B(q128, 0, v128); // CHECK: @llvm.hexagon.V6.vmaxb.128B __builtin_HEXAGON_V6_vmaxb_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vmaxh.128B @@ -566,7 +567,7 @@ void test() { // CHECK: @llvm.hexagon.V6.vmpyuhv.acc.128B __builtin_HEXAGON_V6_vmpyuhv_acc_128B(v256, v128, v128); // CHECK: @llvm.hexagon.V6.vmux.128B - __builtin_HEXAGON_V6_vmux_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vmux_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vnavgb.128B __builtin_HEXAGON_V6_vnavgb_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vnavgh.128B @@ -602,11 +603,11 @@ void test() { // CHECK: @llvm.hexagon.V6.vpopcounth.128B __builtin_HEXAGON_V6_vpopcounth_128B(v128); // CHECK: @llvm.hexagon.V6.vprefixqb.128B - __builtin_HEXAGON_V6_vprefixqb_128B(v128); + __builtin_HEXAGON_V6_vprefixqb_128B(q128); // CHECK: @llvm.hexagon.V6.vprefixqh.128B - __builtin_HEXAGON_V6_vprefixqh_128B(v128); + __builtin_HEXAGON_V6_vprefixqh_128B(q128); // CHECK: @llvm.hexagon.V6.vprefixqw.128B - __builtin_HEXAGON_V6_vprefixqw_128B(v128); + __builtin_HEXAGON_V6_vprefixqw_128B(q128); // CHECK: @llvm.hexagon.V6.vrdelta.128B __builtin_HEXAGON_V6_vrdelta_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.128B @@ -676,19 +677,19 @@ void test() { // CHECK: @llvm.hexagon.V6.vscattermh.add.128B __builtin_HEXAGON_V6_vscattermh_add_128B(0, 0, v128, v128); // CHECK: @llvm.hexagon.V6.vscattermhq.128B - __builtin_HEXAGON_V6_vscattermhq_128B(v128, 0, 0, v128, v128); + __builtin_HEXAGON_V6_vscattermhq_128B(q128, 0, 0, v128, v128); // CHECK: @llvm.hexagon.V6.vscattermhw.128B __builtin_HEXAGON_V6_vscattermhw_128B(0, 0, v256, v128); // CHECK: @llvm.hexagon.V6.vscattermhw.add.128B __builtin_HEXAGON_V6_vscattermhw_add_128B(0, 0, v256, v128); // CHECK: @llvm.hexagon.V6.vscattermhwq.128B - __builtin_HEXAGON_V6_vscattermhwq_128B(v128, 0, 0, v256, v128); + __builtin_HEXAGON_V6_vscattermhwq_128B(q128, 0, 0, v256, v128); // CHECK: @llvm.hexagon.V6.vscattermw.128B __builtin_HEXAGON_V6_vscattermw_128B(0, 0, v128, v128); // CHECK: @llvm.hexagon.V6.vscattermw.add.128B __builtin_HEXAGON_V6_vscattermw_add_128B(0, 0, v128, v128); // CHECK: @llvm.hexagon.V6.vscattermwq.128B - __builtin_HEXAGON_V6_vscattermwq_128B(v128, 0, 0, v128, v128); + __builtin_HEXAGON_V6_vscattermwq_128B(q128, 0, 0, v128, v128); // CHECK: @llvm.hexagon.V6.vsh.128B __builtin_HEXAGON_V6_vsh_128B(v128); // CHECK: @llvm.hexagon.V6.vshufeh.128B @@ -714,9 +715,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubb.dv.128B __builtin_HEXAGON_V6_vsubb_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vsubbnq.128B - __builtin_HEXAGON_V6_vsubbnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubbnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubbq.128B - __builtin_HEXAGON_V6_vsubbq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubbq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubbsat.128B __builtin_HEXAGON_V6_vsubbsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vsubbsat.dv.128B @@ -728,9 +729,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubh.dv.128B __builtin_HEXAGON_V6_vsubh_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vsubhnq.128B - __builtin_HEXAGON_V6_vsubhnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubhnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubhq.128B - __builtin_HEXAGON_V6_vsubhq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubhq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubhsat.128B __builtin_HEXAGON_V6_vsubhsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vsubhsat.dv.128B @@ -760,15 +761,15 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubw.dv.128B __builtin_HEXAGON_V6_vsubw_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vsubwnq.128B - __builtin_HEXAGON_V6_vsubwnq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubwnq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubwq.128B - __builtin_HEXAGON_V6_vsubwq_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vsubwq_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vsubwsat.128B __builtin_HEXAGON_V6_vsubwsat_128B(v128, v128); // CHECK: @llvm.hexagon.V6.vsubwsat.dv.128B __builtin_HEXAGON_V6_vsubwsat_dv_128B(v256, v256); // CHECK: @llvm.hexagon.V6.vswap.128B - __builtin_HEXAGON_V6_vswap_128B(v128, v128, v128); + __builtin_HEXAGON_V6_vswap_128B(q128, v128, v128); // CHECK: @llvm.hexagon.V6.vtmpyb.128B __builtin_HEXAGON_V6_vtmpyb_128B(v256, 0); // CHECK: @llvm.hexagon.V6.vtmpyb.acc.128B diff --git a/clang/test/CodeGen/builtins-hvx64.c b/clang/test/CodeGen/builtins-hvx64.c index 5a53296e72768..27d39990adb54 100644 --- a/clang/test/CodeGen/builtins-hvx64.c +++ b/clang/test/CodeGen/builtins-hvx64.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length64b -emit-llvm %s -o - | FileCheck %s void test() { + int q64 __attribute__((__vector_size__(64))); int v64 __attribute__((__vector_size__(64))); int v128 __attribute__((__vector_size__(128))); @@ -18,33 +19,33 @@ void test() { // CHECK: @llvm.hexagon.V6.lvsplatw __builtin_HEXAGON_V6_lvsplatw(0); // CHECK: @llvm.hexagon.V6.pred.and - __builtin_HEXAGON_V6_pred_and(v64, v64); + __builtin_HEXAGON_V6_pred_and(q64, q64); // CHECK: @llvm.hexagon.V6.pred.and.n - __builtin_HEXAGON_V6_pred_and_n(v64, v64); + __builtin_HEXAGON_V6_pred_and_n(q64, q64); // CHECK: @llvm.hexagon.V6.pred.not - __builtin_HEXAGON_V6_pred_not(v64); + __builtin_HEXAGON_V6_pred_not(q64); // CHECK: @llvm.hexagon.V6.pred.or - __builtin_HEXAGON_V6_pred_or(v64, v64); + __builtin_HEXAGON_V6_pred_or(q64, q64); // CHECK: @llvm.hexagon.V6.pred.or.n - __builtin_HEXAGON_V6_pred_or_n(v64, v64); + __builtin_HEXAGON_V6_pred_or_n(q64, q64); // CHECK: @llvm.hexagon.V6.pred.scalar2 __builtin_HEXAGON_V6_pred_scalar2(0); // CHECK: @llvm.hexagon.V6.pred.scalar2v2 __builtin_HEXAGON_V6_pred_scalar2v2(0); // CHECK: @llvm.hexagon.V6.pred.xor - __builtin_HEXAGON_V6_pred_xor(v64, v64); + __builtin_HEXAGON_V6_pred_xor(q64, q64); // CHECK: @llvm.hexagon.V6.shuffeqh - __builtin_HEXAGON_V6_shuffeqh(v64, v64); + __builtin_HEXAGON_V6_shuffeqh(q64, q64); // CHECK: @llvm.hexagon.V6.shuffeqw - __builtin_HEXAGON_V6_shuffeqw(v64, v64); + __builtin_HEXAGON_V6_shuffeqw(q64, q64); // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai - __builtin_HEXAGON_V6_vS32b_nqpred_ai(v64, 0, v64); + __builtin_HEXAGON_V6_vS32b_nqpred_ai(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai - __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(v64, 0, v64); + __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai - __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(v64, 0, v64); + __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai - __builtin_HEXAGON_V6_vS32b_qpred_ai(v64, 0, v64); + __builtin_HEXAGON_V6_vS32b_qpred_ai(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vabsb __builtin_HEXAGON_V6_vabsb(v64); // CHECK: @llvm.hexagon.V6.vabsb.sat @@ -70,9 +71,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddb.dv __builtin_HEXAGON_V6_vaddb_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vaddbnq - __builtin_HEXAGON_V6_vaddbnq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddbnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddbq - __builtin_HEXAGON_V6_vaddbq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddbq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddbsat __builtin_HEXAGON_V6_vaddbsat(v64, v64); // CHECK: @llvm.hexagon.V6.vaddbsat.dv @@ -88,9 +89,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddh.dv __builtin_HEXAGON_V6_vaddh_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vaddhnq - __builtin_HEXAGON_V6_vaddhnq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddhnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddhq - __builtin_HEXAGON_V6_vaddhq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddhq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddhsat __builtin_HEXAGON_V6_vaddhsat(v64, v64); // CHECK: @llvm.hexagon.V6.vaddhsat.dv @@ -126,9 +127,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vaddw.dv __builtin_HEXAGON_V6_vaddw_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vaddwnq - __builtin_HEXAGON_V6_vaddwnq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddwnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddwq - __builtin_HEXAGON_V6_vaddwq(v64, v64, v64); + __builtin_HEXAGON_V6_vaddwq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vaddwsat __builtin_HEXAGON_V6_vaddwsat(v64, v64); // CHECK: @llvm.hexagon.V6.vaddwsat.dv @@ -140,21 +141,21 @@ void test() { // CHECK: @llvm.hexagon.V6.vand __builtin_HEXAGON_V6_vand(v64, v64); // CHECK: @llvm.hexagon.V6.vandnqrt - __builtin_HEXAGON_V6_vandnqrt(v64, 0); + __builtin_HEXAGON_V6_vandnqrt(q64, 0); // CHECK: @llvm.hexagon.V6.vandnqrt.acc - __builtin_HEXAGON_V6_vandnqrt_acc(v64, v64, 0); + __builtin_HEXAGON_V6_vandnqrt_acc(v64, q64, 0); // CHECK: @llvm.hexagon.V6.vandqrt - __builtin_HEXAGON_V6_vandqrt(v64, 0); + __builtin_HEXAGON_V6_vandqrt(q64, 0); // CHECK: @llvm.hexagon.V6.vandqrt.acc - __builtin_HEXAGON_V6_vandqrt_acc(v64, v64, 0); + __builtin_HEXAGON_V6_vandqrt_acc(v64, q64, 0); // CHECK: @llvm.hexagon.V6.vandvnqv - __builtin_HEXAGON_V6_vandvnqv(v64, v64); + __builtin_HEXAGON_V6_vandvnqv(q64, v64); // CHECK: @llvm.hexagon.V6.vandvqv - __builtin_HEXAGON_V6_vandvqv(v64, v64); + __builtin_HEXAGON_V6_vandvqv(q64, v64); // CHECK: @llvm.hexagon.V6.vandvrt __builtin_HEXAGON_V6_vandvrt(v64, 0); // CHECK: @llvm.hexagon.V6.vandvrt.acc - __builtin_HEXAGON_V6_vandvrt_acc(v64, v64, 0); + __builtin_HEXAGON_V6_vandvrt_acc(q64, v64, 0); // CHECK: @llvm.hexagon.V6.vaslh __builtin_HEXAGON_V6_vaslh(v64, 0); // CHECK: @llvm.hexagon.V6.vaslh.acc @@ -296,87 +297,87 @@ void test() { // CHECK: @llvm.hexagon.V6.veqb __builtin_HEXAGON_V6_veqb(v64, v64); // CHECK: @llvm.hexagon.V6.veqb.and - __builtin_HEXAGON_V6_veqb_and(v64, v64, v64); + __builtin_HEXAGON_V6_veqb_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqb.or - __builtin_HEXAGON_V6_veqb_or(v64, v64, v64); + __builtin_HEXAGON_V6_veqb_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqb.xor - __builtin_HEXAGON_V6_veqb_xor(v64, v64, v64); + __builtin_HEXAGON_V6_veqb_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqh __builtin_HEXAGON_V6_veqh(v64, v64); // CHECK: @llvm.hexagon.V6.veqh.and - __builtin_HEXAGON_V6_veqh_and(v64, v64, v64); + __builtin_HEXAGON_V6_veqh_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqh.or - __builtin_HEXAGON_V6_veqh_or(v64, v64, v64); + __builtin_HEXAGON_V6_veqh_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqh.xor - __builtin_HEXAGON_V6_veqh_xor(v64, v64, v64); + __builtin_HEXAGON_V6_veqh_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqw __builtin_HEXAGON_V6_veqw(v64, v64); // CHECK: @llvm.hexagon.V6.veqw.and - __builtin_HEXAGON_V6_veqw_and(v64, v64, v64); + __builtin_HEXAGON_V6_veqw_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqw.or - __builtin_HEXAGON_V6_veqw_or(v64, v64, v64); + __builtin_HEXAGON_V6_veqw_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.veqw.xor - __builtin_HEXAGON_V6_veqw_xor(v64, v64, v64); + __builtin_HEXAGON_V6_veqw_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgathermh __builtin_HEXAGON_V6_vgathermh(0, 0, 0, v64); // CHECK: @llvm.hexagon.V6.vgathermhq - __builtin_HEXAGON_V6_vgathermhq(0, v64, 0, 0, v64); + __builtin_HEXAGON_V6_vgathermhq(0, q64, 0, 0, v64); // CHECK: @llvm.hexagon.V6.vgathermhw __builtin_HEXAGON_V6_vgathermhw(0, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgathermhwq - __builtin_HEXAGON_V6_vgathermhwq(0, v64, 0, 0, v128); + __builtin_HEXAGON_V6_vgathermhwq(0, q64, 0, 0, v128); // CHECK: @llvm.hexagon.V6.vgathermw __builtin_HEXAGON_V6_vgathermw(0, 0, 0, v64); // CHECK: @llvm.hexagon.V6.vgathermwq - __builtin_HEXAGON_V6_vgathermwq(0, v64, 0, 0, v64); + __builtin_HEXAGON_V6_vgathermwq(0, q64, 0, 0, v64); // CHECK: @llvm.hexagon.V6.vgtb __builtin_HEXAGON_V6_vgtb(v64, v64); // CHECK: @llvm.hexagon.V6.vgtb.and - __builtin_HEXAGON_V6_vgtb_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgtb_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtb.or - __builtin_HEXAGON_V6_vgtb_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgtb_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtb.xor - __builtin_HEXAGON_V6_vgtb_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgtb_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgth __builtin_HEXAGON_V6_vgth(v64, v64); // CHECK: @llvm.hexagon.V6.vgth.and - __builtin_HEXAGON_V6_vgth_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgth_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgth.or - __builtin_HEXAGON_V6_vgth_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgth_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgth.xor - __builtin_HEXAGON_V6_vgth_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgth_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtub __builtin_HEXAGON_V6_vgtub(v64, v64); // CHECK: @llvm.hexagon.V6.vgtub.and - __builtin_HEXAGON_V6_vgtub_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgtub_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtub.or - __builtin_HEXAGON_V6_vgtub_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgtub_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtub.xor - __builtin_HEXAGON_V6_vgtub_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgtub_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuh __builtin_HEXAGON_V6_vgtuh(v64, v64); // CHECK: @llvm.hexagon.V6.vgtuh.and - __builtin_HEXAGON_V6_vgtuh_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuh_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuh.or - __builtin_HEXAGON_V6_vgtuh_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuh_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuh.xor - __builtin_HEXAGON_V6_vgtuh_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuh_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuw __builtin_HEXAGON_V6_vgtuw(v64, v64); // CHECK: @llvm.hexagon.V6.vgtuw.and - __builtin_HEXAGON_V6_vgtuw_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuw_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuw.or - __builtin_HEXAGON_V6_vgtuw_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuw_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtuw.xor - __builtin_HEXAGON_V6_vgtuw_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgtuw_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtw __builtin_HEXAGON_V6_vgtw(v64, v64); // CHECK: @llvm.hexagon.V6.vgtw.and - __builtin_HEXAGON_V6_vgtw_and(v64, v64, v64); + __builtin_HEXAGON_V6_vgtw_and(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtw.or - __builtin_HEXAGON_V6_vgtw_or(v64, v64, v64); + __builtin_HEXAGON_V6_vgtw_or(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vgtw.xor - __builtin_HEXAGON_V6_vgtw_xor(v64, v64, v64); + __builtin_HEXAGON_V6_vgtw_xor(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vinsertwr __builtin_HEXAGON_V6_vinsertwr(v64, 0); // CHECK: @llvm.hexagon.V6.vlalignb @@ -416,13 +417,13 @@ void test() { // CHECK: @llvm.hexagon.V6.vlutvwhi __builtin_HEXAGON_V6_vlutvwhi(v64, v64, 0); // CHECK: @llvm.hexagon.V6.vmaskedstorenq - __builtin_HEXAGON_V6_vmaskedstorenq(v64, 0, v64); + __builtin_HEXAGON_V6_vmaskedstorenq(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vmaskedstorentnq - __builtin_HEXAGON_V6_vmaskedstorentnq(v64, 0, v64); + __builtin_HEXAGON_V6_vmaskedstorentnq(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vmaskedstorentq - __builtin_HEXAGON_V6_vmaskedstorentq(v64, 0, v64); + __builtin_HEXAGON_V6_vmaskedstorentq(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vmaskedstoreq - __builtin_HEXAGON_V6_vmaskedstoreq(v64, 0, v64); + __builtin_HEXAGON_V6_vmaskedstoreq(q64, 0, v64); // CHECK: @llvm.hexagon.V6.vmaxb __builtin_HEXAGON_V6_vmaxb(v64, v64); // CHECK: @llvm.hexagon.V6.vmaxh @@ -566,7 +567,7 @@ void test() { // CHECK: @llvm.hexagon.V6.vmpyuhv.acc __builtin_HEXAGON_V6_vmpyuhv_acc(v128, v64, v64); // CHECK: @llvm.hexagon.V6.vmux - __builtin_HEXAGON_V6_vmux(v64, v64, v64); + __builtin_HEXAGON_V6_vmux(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vnavgb __builtin_HEXAGON_V6_vnavgb(v64, v64); // CHECK: @llvm.hexagon.V6.vnavgh @@ -602,11 +603,11 @@ void test() { // CHECK: @llvm.hexagon.V6.vpopcounth __builtin_HEXAGON_V6_vpopcounth(v64); // CHECK: @llvm.hexagon.V6.vprefixqb - __builtin_HEXAGON_V6_vprefixqb(v64); + __builtin_HEXAGON_V6_vprefixqb(q64); // CHECK: @llvm.hexagon.V6.vprefixqh - __builtin_HEXAGON_V6_vprefixqh(v64); + __builtin_HEXAGON_V6_vprefixqh(q64); // CHECK: @llvm.hexagon.V6.vprefixqw - __builtin_HEXAGON_V6_vprefixqw(v64); + __builtin_HEXAGON_V6_vprefixqw(q64); // CHECK: @llvm.hexagon.V6.vrdelta __builtin_HEXAGON_V6_vrdelta(v64, v64); // CHECK: @llvm.hexagon.V6.vrmpybub.rtt @@ -676,19 +677,19 @@ void test() { // CHECK: @llvm.hexagon.V6.vscattermh.add __builtin_HEXAGON_V6_vscattermh_add(0, 0, v64, v64); // CHECK: @llvm.hexagon.V6.vscattermhq - __builtin_HEXAGON_V6_vscattermhq(v64, 0, 0, v64, v64); + __builtin_HEXAGON_V6_vscattermhq(q64, 0, 0, v64, v64); // CHECK: @llvm.hexagon.V6.vscattermhw __builtin_HEXAGON_V6_vscattermhw(0, 0, v128, v64); // CHECK: @llvm.hexagon.V6.vscattermhw.add __builtin_HEXAGON_V6_vscattermhw_add(0, 0, v128, v64); // CHECK: @llvm.hexagon.V6.vscattermhwq - __builtin_HEXAGON_V6_vscattermhwq(v64, 0, 0, v128, v64); + __builtin_HEXAGON_V6_vscattermhwq(q64, 0, 0, v128, v64); // CHECK: @llvm.hexagon.V6.vscattermw __builtin_HEXAGON_V6_vscattermw(0, 0, v64, v64); // CHECK: @llvm.hexagon.V6.vscattermw.add __builtin_HEXAGON_V6_vscattermw_add(0, 0, v64, v64); // CHECK: @llvm.hexagon.V6.vscattermwq - __builtin_HEXAGON_V6_vscattermwq(v64, 0, 0, v64, v64); + __builtin_HEXAGON_V6_vscattermwq(q64, 0, 0, v64, v64); // CHECK: @llvm.hexagon.V6.vsh __builtin_HEXAGON_V6_vsh(v64); // CHECK: @llvm.hexagon.V6.vshufeh @@ -714,9 +715,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubb.dv __builtin_HEXAGON_V6_vsubb_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vsubbnq - __builtin_HEXAGON_V6_vsubbnq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubbnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubbq - __builtin_HEXAGON_V6_vsubbq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubbq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubbsat __builtin_HEXAGON_V6_vsubbsat(v64, v64); // CHECK: @llvm.hexagon.V6.vsubbsat.dv @@ -728,9 +729,9 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubh.dv __builtin_HEXAGON_V6_vsubh_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vsubhnq - __builtin_HEXAGON_V6_vsubhnq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubhnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubhq - __builtin_HEXAGON_V6_vsubhq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubhq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubhsat __builtin_HEXAGON_V6_vsubhsat(v64, v64); // CHECK: @llvm.hexagon.V6.vsubhsat.dv @@ -760,15 +761,15 @@ void test() { // CHECK: @llvm.hexagon.V6.vsubw.dv __builtin_HEXAGON_V6_vsubw_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vsubwnq - __builtin_HEXAGON_V6_vsubwnq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubwnq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubwq - __builtin_HEXAGON_V6_vsubwq(v64, v64, v64); + __builtin_HEXAGON_V6_vsubwq(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vsubwsat __builtin_HEXAGON_V6_vsubwsat(v64, v64); // CHECK: @llvm.hexagon.V6.vsubwsat.dv __builtin_HEXAGON_V6_vsubwsat_dv(v128, v128); // CHECK: @llvm.hexagon.V6.vswap - __builtin_HEXAGON_V6_vswap(v64, v64, v64); + __builtin_HEXAGON_V6_vswap(q64, v64, v64); // CHECK: @llvm.hexagon.V6.vtmpyb __builtin_HEXAGON_V6_vtmpyb(v128, 0); // CHECK: @llvm.hexagon.V6.vtmpyb.acc diff --git a/clang/test/CodeGen/codemodels.c b/clang/test/CodeGen/codemodels.c index cc68bf2120c5c..a302016c66d7b 100644 --- a/clang/test/CodeGen/codemodels.c +++ b/clang/test/CodeGen/codemodels.c @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NOMODEL -// RUN: %clang_cc1 -triple aarch64-unknown-none-eabi -emit-llvm -mcode-model tiny %s -o - | FileCheck %s -check-prefix=CHECK-TINY -// RUN: %clang_cc1 -emit-llvm -mcode-model small %s -o - | FileCheck %s -check-prefix=CHECK-SMALL -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcode-model kernel %s -o - | FileCheck %s -check-prefix=CHECK-KERNEL -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcode-model medium %s -o - | FileCheck %s -check-prefix=CHECK-MEDIUM -// RUN: %clang_cc1 -emit-llvm -mcode-model large %s -o - | FileCheck %s -check-prefix=CHECK-LARGE +// RUN: %clang_cc1 -triple aarch64-unknown-none-eabi -emit-llvm -mcmodel=tiny %s -o - | FileCheck %s -check-prefix=CHECK-TINY +// RUN: %clang_cc1 -emit-llvm -mcmodel=small %s -o - | FileCheck %s -check-prefix=CHECK-SMALL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcmodel=kernel %s -o - | FileCheck %s -check-prefix=CHECK-KERNEL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcmodel=medium %s -o - | FileCheck %s -check-prefix=CHECK-MEDIUM +// RUN: %clang_cc1 -emit-llvm -mcmodel=large %s -o - | FileCheck %s -check-prefix=CHECK-LARGE // CHECK-TINY: !llvm.module.flags = !{{{.*}}} // CHECK-TINY: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 0} diff --git a/clang/test/CodeGen/complex-math.c b/clang/test/CodeGen/complex-math.c index e42418ad72c2e..54dee473a364b 100644 --- a/clang/test/CodeGen/complex-math.c +++ b/clang/test/CodeGen/complex-math.c @@ -93,14 +93,15 @@ float _Complex mul_float_rc(float a, float _Complex b) { // X86: ret return a * b; } + float _Complex mul_float_cc(float _Complex a, float _Complex b) { // X86-LABEL: @mul_float_cc( // X86: %[[AC:[^ ]+]] = fmul // X86: %[[BD:[^ ]+]] = fmul // X86: %[[AD:[^ ]+]] = fmul // X86: %[[BC:[^ ]+]] = fmul - // X86: %[[RR:[^ ]+]] = fsub float %[[AC]], %[[BD]] - // X86: %[[RI:[^ ]+]] = fadd float + // X86: %[[RR:[^ ]+]] = fsub + // X86: %[[RI:[^ ]+]] = fadd // X86-DAG: %[[AD]] // X86-DAG: , // X86-DAG: %[[BC]] diff --git a/clang/test/CodeGen/fma-builtins-constrained.c b/clang/test/CodeGen/fma-builtins-constrained.c index fe5b946fe6404..6b299278b1084 100644 --- a/clang/test/CodeGen/fma-builtins-constrained.c +++ b/clang/test/CodeGen/fma-builtins-constrained.c @@ -184,53 +184,33 @@ __m128d test_mm_fnmsub_sd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_fmaddsub_ps(__m128 a, __m128 b, __m128 c) { // COMMON-LABEL: test_mm_fmaddsub_ps - // UNCONSTRAINED: [[ADD:%.+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, metadata !{{.*}}) - // COMMONIR: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]], metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmaddsub213ps - // CHECK-ASM-CONSTRAINED-NOT: vfmaddsub213ps - // COMMONIR: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // COMMONIR-NOT: fneg + // COMMONIR: tail call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK-ASM: vfmaddsub213ps return _mm_fmaddsub_ps(a, b, c); } __m128d test_mm_fmaddsub_pd(__m128d a, __m128d b, __m128d c) { // COMMON-LABEL: test_mm_fmaddsub_pd - // UNCONSTRAINED: [[ADD:%.+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, metadata !{{.*}}) - // COMMONIR: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]], metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmaddsub213pd - // CHECK-ASM-CONSTRAINED-NOT: vfmaddsub213pd - // COMMONIR: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // COMMONIR-NOT: fneg + // COMMONIR: tail call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK-ASM: vfmaddsub213pd return _mm_fmaddsub_pd(a, b, c); } __m128 test_mm_fmsubadd_ps(__m128 a, __m128 b, __m128 c) { // COMMON-LABEL: test_mm_fmsubadd_ps - // COMMONIR: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CONSTRAINED: [[SUB:%.+]] = tail call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]], metadata !{{.*}}) - // UNCONSTRAINED: [[ADD:%.+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmsubadd213ps - // CHECK-ASM-CONSTRAINED-NOT: vfmsubadd213ps - // COMMONIR: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // COMMONIR: [[FNEG:%.+]] = fneg <4 x float> %{{.*}} + // COMMONIR: tail call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[FNEG]]) + // CHECK-ASM: vfmsubadd213ps return _mm_fmsubadd_ps(a, b, c); } __m128d test_mm_fmsubadd_pd(__m128d a, __m128d b, __m128d c) { // COMMON-LABEL: test_mm_fmsubadd_pd - // COMMONIR: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]], metadata !{{.*}}) - // UNCONSTRAINED: [[ADD:%.+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmsubadd213pd - // CHECK-ASM-CONSTRAINED-NOT: vfmsubadd213pd - // COMMONIR: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // COMMONIR: [[FNEG:%.+]] = fneg <2 x double> %{{.*}} + // COMMONIR: tail call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[FNEG]]) + // CHECK-ASM: vfmsubadd213pd return _mm_fmsubadd_pd(a, b, c); } @@ -308,52 +288,32 @@ __m256d test_mm256_fnmsub_pd(__m256d a, __m256d b, __m256d c) { __m256 test_mm256_fmaddsub_ps(__m256 a, __m256 b, __m256 c) { // COMMON-LABEL: test_mm256_fmaddsub_ps - // UNCONSTRAINED: [[ADD:%.+]] = tail call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // COMMONIR: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]], metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmaddsub213ps - // CHECK-ASM-CONSTRAINED-NOT: vfmaddsub213ps - // COMMONIR: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // COMMONIR-NOT: fneg + // COMMONIR: tail call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK-ASM: vfmaddsub213ps return _mm256_fmaddsub_ps(a, b, c); } __m256d test_mm256_fmaddsub_pd(__m256d a, __m256d b, __m256d c) { // COMMON-LABEL: test_mm256_fmaddsub_pd - // UNCONSTRAINED: [[ADD:%.+]] = tail call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}, metadata !{{.*}}) - // COMMONIR: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CONSTRAINED: [[SUB:%.+]] = tail call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}, metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmaddsub213pd - // CHECK-ASM-CONSTRAINED-NOT: vfmaddsub213pd - // COMMONIR: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // COMMONIR-NOT: fneg + // COMMONIR: tail call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK-ASM: vfmaddsub213pd return _mm256_fmaddsub_pd(a, b, c); } __m256 test_mm256_fmsubadd_ps(__m256 a, __m256 b, __m256 c) { // COMMON-LABEL: test_mm256_fmsubadd_ps - // COMMONIR: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]], metadata !{{.*}}) - // UNCONSTRAINED: [[ADD:%.+]] = tail call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}, metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmsubadd213ps - // CHECK-ASM-CONSTRAINED-NOT: vfmsubadd213ps - // COMMONIR: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // COMMONIR: [[FNEG:%.+]] = fneg <8 x float> %{{.*}} + // COMMONIR: tail call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[FNEG]]) + // CHECK-ASM: vfmsubadd213ps return _mm256_fmsubadd_ps(a, b, c); } __m256d test_mm256_fmsubadd_pd(__m256d a, __m256d b, __m256d c) { // COMMON-LABEL: test_mm256_fmsubadd_pd - // COMMONIR: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // UNCONSTRAINED: [[SUB:%.+]] = tail call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) - // CONSTRAINED: [[SUB:%.+]] = tail call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]], metadata !{{.*}}) - // UNCONSTRAINED: [[ADD:%.+]] = tail call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CONSTRAINED: [[ADD:%.+]] = tail call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}, metadata !{{.*}}) - // CHECK-ASM-UNCONSTRAINED: vfmsubadd213pd - // CHECK-ASM-CONSTRAINED-NOT: vfmsubadd213pd - // COMMONIR: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // COMMONIR: [[FNEG:%.+]] = fneg <4 x double> %{{.*}} + // COMMONIR: tail call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[FNEG]]) + // CHECK-ASM: vfmsubadd213pd return _mm256_fmsubadd_pd(a, b, c); } diff --git a/clang/test/CodeGen/fma-builtins.c b/clang/test/CodeGen/fma-builtins.c index a21f536c1ed92..4686b3686a4f8 100644 --- a/clang/test/CodeGen/fma-builtins.c +++ b/clang/test/CodeGen/fma-builtins.c @@ -149,37 +149,29 @@ __m128d test_mm_fnmsub_sd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_fmaddsub_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) return _mm_fmaddsub_ps(a, b, c); } __m128d test_mm_fmaddsub_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // CHECK-NOT: fneg + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) return _mm_fmaddsub_pd(a, b, c); } __m128 test_mm_fmsubadd_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_fmsubadd_ps // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) return _mm_fmsubadd_ps(a, b, c); } __m128d test_mm_fmsubadd_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) return _mm_fmsubadd_pd(a, b, c); } @@ -241,36 +233,28 @@ __m256d test_mm256_fnmsub_pd(__m256d a, __m256d b, __m256d c) { __m256 test_mm256_fmaddsub_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_fmaddsub_ps - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) return _mm256_fmaddsub_ps(a, b, c); } __m256d test_mm256_fmaddsub_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_fmaddsub_pd - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) return _mm256_fmaddsub_pd(a, b, c); } __m256 test_mm256_fmsubadd_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_fmsubadd_ps - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.+}} + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) return _mm256_fmsubadd_ps(a, b, c); } __m256d test_mm256_fmsubadd_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_fmsubadd_pd // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) return _mm256_fmsubadd_pd(a, b, c); } diff --git a/clang/test/CodeGen/fma4-builtins.c b/clang/test/CodeGen/fma4-builtins.c index 7dc769afbf720..274ca481fabf0 100644 --- a/clang/test/CodeGen/fma4-builtins.c +++ b/clang/test/CodeGen/fma4-builtins.c @@ -149,37 +149,29 @@ __m128d test_mm_nmsub_sd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_maddsub_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_maddsub_ps - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) return _mm_maddsub_ps(a, b, c); } __m128d test_mm_maddsub_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_maddsub_pd - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> + // CHECK-NOT: fneg + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) return _mm_maddsub_pd(a, b, c); } __m128 test_mm_msubadd_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_msubadd_ps // CHECK: [[NEG:%.+]] = fneg <4 x float> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> + // CHECK: call <4 x float> @llvm.x86.fma.vfmaddsub.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]]) return _mm_msubadd_ps(a, b, c); } __m128d test_mm_msubadd_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_msubadd_pd // CHECK: [[NEG:%.+]] = fneg <2 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> + // CHECK: call <2 x double> @llvm.x86.fma.vfmaddsub.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]]) return _mm_msubadd_pd(a, b, c); } @@ -241,36 +233,28 @@ __m256d test_mm256_nmsub_pd(__m256d a, __m256d b, __m256d c) { __m256 test_mm256_maddsub_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_maddsub_ps - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> + // CHECK-NOT: fneg + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) return _mm256_maddsub_ps(a, b, c); } __m256d test_mm256_maddsub_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_maddsub_pd - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: [[NEG:%.+]] = fneg <4 x double> %{{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> + // CHECK-NOT: fneg + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) return _mm256_maddsub_pd(a, b, c); } __m256 test_mm256_msubadd_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_msubadd_ps // CHECK: [[NEG:%.+]] = fneg <8 x float> %{{.*}} - // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] - // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> + // CHECK: call <8 x float> @llvm.x86.fma.vfmaddsub.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]]) return _mm256_msubadd_ps(a, b, c); } __m256d test_mm256_msubadd_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_msubadd_pd // CHECK: [[NEG:%.+]] = fneg <4 x double> {{.+}} - // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] - // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> + // CHECK: call <4 x double> @llvm.x86.fma.vfmaddsub.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]]) return _mm256_msubadd_pd(a, b, c); } diff --git a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c new file mode 100644 index 0000000000000..9467f6228dfc4 --- /dev/null +++ b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s + +void *__attribute__((alloc_align(1))) alloc(int align); + +// CHECK-LABEL: @t0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ALIGN_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 [[TMP0]]) +// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 +// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64 +// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] +// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: ret void +// +void t0(int align) { + alloc(align); +} +// CHECK-LABEL: @t1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 7) +// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64 +// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 6 +// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: ret void +// +void t1(int align) { + alloc(7); +} +// CHECK-LABEL: @t2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call align 8 i8* @alloc(i32 8) +// CHECK-NEXT: ret void +// +void t2(int align) { + alloc(8); +} diff --git a/clang/test/CodeGen/static-init.cpp b/clang/test/CodeGen/static-init.cpp new file mode 100644 index 0000000000000..e336b55a04836 --- /dev/null +++ b/clang/test/CodeGen/static-init.cpp @@ -0,0 +1,12 @@ +// RUN: not %clang_cc1 -triple powerpc-ibm-aix-xcoff -S -emit-llvm -x c++ %s \ +// RUN: -o /dev/null 2>&1 | FileCheck %s + +// RUN: not %clang_cc1 -triple powerpc64-ibm-aix-xcoff -S -emit-llvm -x c++ %s \ +// RUN: -o /dev/null 2>&1 | FileCheck %s + +struct test { + test(); + ~test(); +} t; + +// CHECK: error in backend: Static initialization has not been implemented on XL ABI yet. diff --git a/clang/test/CodeGen/vectorcall.c b/clang/test/CodeGen/vectorcall.c index aa529d0870112..77db600a7f89c 100644 --- a/clang/test/CodeGen/vectorcall.c +++ b/clang/test/CodeGen/vectorcall.c @@ -31,13 +31,13 @@ void __vectorcall hfa1(int a, struct HFA4 b, int c) {} // indirectly. Additional vector arguments can consume the rest of the SSE // registers. void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} -// X32: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* inreg %b, double %c) +// X32: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* inreg %b, double inreg %c) // X64: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, %struct.HFA4* %b, double %c) // Ensure that we pass builtin types directly while counting them against the // SSE register usage. void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {} -// X32: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* inreg %f) +// X32: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double inreg %a, double inreg %b, double inreg %c, double inreg %d, double inreg %e, %struct.HFA2* inreg %f) // X64: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* %f) // Aggregates with more than four elements are not HFAs and are passed byval. @@ -64,21 +64,21 @@ v4f32 __vectorcall hva1(int a, struct HVA4 b, int c) {return b.w;} // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@80"(i32 %a, %struct.HVA4 inreg %b.coerce, i32 %c) v4f32 __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {return c;} -// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b, <4 x float> %c) +// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* inreg %b, <4 x float> inreg %c) // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, %struct.HVA4* %b, <4 x float> %c) v4f32 __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {return f.x;} -// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* inreg %f) +// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> inreg %a, <4 x float> inreg %b, <4 x float> inreg %c, <4 x float> inreg %d, <4 x float> inreg %e, %struct.HVA2* inreg %f) // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* %f) // vector types have higher priority then HVA structures, So vector types are allocated first // and HVAs are allocated if enough registers are available v4f32 __vectorcall hva4(struct HVA4 a, struct HVA2 b, v4f32 c) {return b.y;} -// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* inreg %b, <4 x float> %c) +// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* inreg %b, <4 x float> inreg %c) // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, %struct.HVA2* %b, <4 x float> %c) v4f32 __vectorcall hva5(struct HVA3 a, struct HVA3 b, v4f32 c, struct HVA2 d) {return d.y;} -// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* inreg %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce) +// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* inreg %b, <4 x float> inreg %c, %struct.HVA2 inreg %d.coerce) // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, %struct.HVA3* %b, <4 x float> %c, %struct.HVA2 inreg %d.coerce) struct HVA4 __vectorcall hva6(struct HVA4 a, struct HVA4 b) { return b;} @@ -90,7 +90,7 @@ struct HVA5 __vectorcall hva7() {struct HVA5 a = {}; return a;} // X64: define dso_local x86_vectorcallcc void @"\01hva7@@0"(%struct.HVA5* noalias sret %agg.result) v4f32 __vectorcall hva8(v4f32 a, v4f32 b, v4f32 c, v4f32 d, int e, v4f32 f) {return f;} -// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 inreg %e, <4 x float> %f) +// X32: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> inreg %a, <4 x float> inreg %b, <4 x float> inreg %c, <4 x float> inreg %d, i32 inreg %e, <4 x float> inreg %f) // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@88"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, i32 %e, <4 x float> %f) typedef float __attribute__((ext_vector_type(3))) v3f32; @@ -104,7 +104,7 @@ void __vectorcall odd_size_hva(struct OddSizeHVA a) {} // consider 'p7' as a register. Instead p5 gets put into the register on the second pass. // x86 should pass p2, p6 and p7 in registers, then p1 in the second pass. struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, int p4, struct HFA2 p5, float p6, float p7, int p8){ return p1;} -// X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* inreg %p3, i32 inreg %p4, %struct.HFA2* %p5, float %p6, float %p7, i32 %p8) +// X32: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float inreg %p2, %struct.HFA4* inreg %p3, i32 inreg %p4, %struct.HFA2* %p5, float inreg %p6, float inreg %p7, i32 %p8) // X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float %p2, %struct.HFA4* %p3, i32 %p4, %struct.HFA2 inreg %p5.coerce, float %p6, float %p7, i32 %p8) // Vectorcall in both architectures allows passing of an HVA as long as there is room, @@ -113,7 +113,7 @@ struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, // in a register, does NOT put p7 in a register (since theres no room), then puts // p8 in a register. void __vectorcall HVAAnywhere(struct HFA2 p1, int p2, int p3, float p4, int p5, int p6, struct HFA4 p7, struct HFA2 p8, float p9){} -// X32: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg %p2, i32 inreg %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9) +// X32: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg %p2, i32 inreg %p3, float inreg %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float inreg %p9) // X64: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 %p2, i32 %p3, float %p4, i32 %p5, i32 %p6, %struct.HFA4* %p7, %struct.HFA2 inreg %p8.coerce, float %p9) #ifndef __x86_64__ @@ -127,12 +127,12 @@ void __vectorcall vectorcall_indirect_vec( } // X32: define dso_local x86_vectorcallcc void @"\01vectorcall_indirect_vec@@{{[0-9]+}}" -// X32-SAME: (double %xmm0, -// X32-SAME: double %xmm1, -// X32-SAME: double %xmm2, -// X32-SAME: double %xmm3, -// X32-SAME: double %xmm4, -// X32-SAME: <4 x float> %xmm5, +// X32-SAME: (double inreg %xmm0, +// X32-SAME: double inreg %xmm1, +// X32-SAME: double inreg %xmm2, +// X32-SAME: double inreg %xmm3, +// X32-SAME: double inreg %xmm4, +// X32-SAME: <4 x float> inreg %xmm5, // X32-SAME: <4 x float>* inreg %0, // X32-SAME: i32 inreg %edx, // X32-SAME: <4 x float>* %1) diff --git a/clang/test/CodeGen/xcoff-comdat.cpp b/clang/test/CodeGen/xcoff-comdat.cpp new file mode 100644 index 0000000000000..7da8d9a2cc225 --- /dev/null +++ b/clang/test/CodeGen/xcoff-comdat.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -o - %s | FileCheck %s + +class a { + virtual void d() {} + virtual void e(); +}; +void a::e() {} + +// CHECK-NOT: = comdat diff --git a/clang/test/CodeGenCUDA/builtins-amdgcn.cu b/clang/test/CodeGenCUDA/builtins-amdgcn.cu index 409a917b352eb..5469e78ea101a 100644 --- a/clang/test/CodeGenCUDA/builtins-amdgcn.cu +++ b/clang/test/CodeGenCUDA/builtins-amdgcn.cu @@ -2,8 +2,8 @@ #include "Inputs/cuda.h" // CHECK-LABEL: @_Z16use_dispatch_ptrPi( -// CHECK: %[[PTR:.*]] = call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() -// CHECK: %{{.*}} = addrspacecast i8 addrspace(4)* %[[PTR]] to i8 addrspace(4)** +// CHECK: %[[PTR:.*]] = call align 4 dereferenceable(64) i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() +// CHECK: %{{.*}} = addrspacecast i8 addrspace(4)* %[[PTR]] to i8* __global__ void use_dispatch_ptr(int* out) { const int* dispatch_ptr = (const int*)__builtin_amdgcn_dispatch_ptr(); *out = *dispatch_ptr; diff --git a/clang/test/CodeGenCXX/inalloca-vector.cpp b/clang/test/CodeGenCXX/inalloca-vector.cpp index f3d7f81e94439..ad04e046d21d4 100644 --- a/clang/test/CodeGenCXX/inalloca-vector.cpp +++ b/clang/test/CodeGenCXX/inalloca-vector.cpp @@ -66,14 +66,13 @@ void __vectorcall vectorcall_receive_vec(double xmm0, double xmm1, double xmm2, __m128 w, int edx, __m128 q, NonTrivial nt) { gv128 = x + y + z + w + q; } -// FIXME: Enable these checks, clang generates wrong IR. // CHECK-LABEL: define dso_local x86_vectorcallcc void @"?vectorcall_receive_vec@@Y{{[^"]*}}" -// CHECKX-SAME: (double inreg %xmm0, -// CHECKX-SAME: double inreg %xmm1, -// CHECKX-SAME: double inreg %xmm2, -// CHECKX-SAME: <4 x float> inreg %x, -// CHECKX-SAME: <4 x float> inreg %y, -// CHECKX-SAME: <4 x float> inreg %z, -// CHECKX-SAME: <4 x float>* inreg %0, -// CHECKX-SAME: i32 inreg %edx, -// CHECKX-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1) +// CHECK-SAME: (double inreg %xmm0, +// CHECK-SAME: double inreg %xmm1, +// CHECK-SAME: double inreg %xmm2, +// CHECK-SAME: <4 x float> inreg %x, +// CHECK-SAME: <4 x float> inreg %y, +// CHECK-SAME: <4 x float> inreg %z, +// CHECK-SAME: <4 x float>* inreg %0, +// CHECK-SAME: i32 inreg %edx, +// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1) diff --git a/clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp b/clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp new file mode 100644 index 0000000000000..aed2cf13f8928 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp @@ -0,0 +1,57 @@ +// Tests that coroutine passes are added to and run by the new pass manager +// pipeline, at -O0 and above. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \ +// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \ +// RUN: -O0 %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \ +// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \ +// RUN: -O1 %s 2>&1 | FileCheck %s +// +// CHECK: Starting llvm::Module pass manager run. +// CHECK: Running pass:{{.*}}CoroEarlyPass +// +// The first coro-split pass enqueues a second run of the entire CGSCC pipeline. +// CHECK: Starting CGSCC pass manager run. +// CHECK: Running pass: CoroSplitPass on (_Z3foov) +// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on (_Z3foov) +// CHECK: Finished CGSCC pass manager run. +// +// The second coro-split pass splits coroutine 'foo' into funclets +// 'foo.resume', 'foo.destroy', and 'foo.cleanup'. +// CHECK: Starting CGSCC pass manager run. +// CHECK: Running pass: CoroSplitPass on (_Z3foov) +// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on (_Z3foov) +// CHECK: Finished CGSCC pass manager run. +// +// CHECK: Running pass:{{.*}}CoroCleanupPass +// CHECK: Finished llvm::Module pass manager run. + +namespace std { +namespace experimental { + +struct handle {}; + +struct awaitable { + bool await_ready() { return true; } + void await_suspend(handle) {} + bool await_resume() { return true; } +}; + +template struct coroutine_handle { + static handle from_address(void *address) { return {}; } +}; + +template struct coroutine_traits { + struct promise_type { + awaitable initial_suspend() { return {}; } + awaitable final_suspend() { return {}; } + void return_void() {} + T get_return_object() { return T(); } + void unhandled_exception() {} + }; +}; +} // namespace experimental +} // namespace std + +void foo() { co_return; } diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl index 6cda2a767d94b..85e921cbe12a1 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -461,7 +461,7 @@ void test_read_exec_hi(global uint* out) { } // CHECK-LABEL: @test_dispatch_ptr -// CHECK: call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() +// CHECK: call align 4 dereferenceable(64) i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() void test_dispatch_ptr(__constant unsigned char ** out) { *out = __builtin_amdgcn_dispatch_ptr(); diff --git a/clang/test/CodeGenSYCL/fpga_pipes.cpp b/clang/test/CodeGenSYCL/fpga_pipes.cpp index 8c8c5120348a2..2eddd5fe7383b 100644 --- a/clang/test/CodeGenSYCL/fpga_pipes.cpp +++ b/clang/test/CodeGenSYCL/fpga_pipes.cpp @@ -11,6 +11,39 @@ RPipeTy RPipeCreator(); template void foo(PipeTy Pipe) {} +struct PipeStorageTy { + int Size; +}; + +// CHECK: @{{.*}}Storage = {{.*}} !io_pipe_id ![[ID0:[0-9]+]] +constexpr PipeStorageTy + Storage __attribute__((io_pipe_id(1))) = {1}; + +// CHECK: @{{.*}}TempStorage{{.*}} = {{.*}} !io_pipe_id ![[ID1:[0-9]+]] +template +constexpr PipeStorageTy + TempStorage __attribute__((io_pipe_id(N))) = {2}; + +void boo(PipeStorageTy PipeStorage); + +template +struct ethernet_pipe { + static constexpr int id = ID; +}; + +// CHECK: @{{.*}}PipeStorage{{.*}} = {{.*}} !io_pipe_id ![[ID2:[0-9]+]] +template +class pipe { +public: + static void read() { + boo(PipeStorage); + } + +private: + static constexpr PipeStorageTy + PipeStorage __attribute__((io_pipe_id(name::id))) = {3}; +}; + template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); @@ -24,7 +57,12 @@ int main() { RPipeTy rpipe = RPipeCreator(); foo(wpipe); foo(rpipe); + boo(Storage); + boo(TempStorage<2>); + pipe>::read(); }); return 0; } - +// CHECK: ![[ID0]] = !{i32 1} +// CHECK: ![[ID1]] = !{i32 2} +// CHECK: ![[ID2]] = !{i32 42} diff --git a/clang/test/CodeGenSYCL/hier_par.cpp b/clang/test/CodeGenSYCL/hier_par.cpp index 557d9845b1276..6967600c2761b 100644 --- a/clang/test/CodeGenSYCL/hier_par.cpp +++ b/clang/test/CodeGenSYCL/hier_par.cpp @@ -16,7 +16,7 @@ // // This is compile-only test for now. // - +// XFAIL:* #include "sycl.hpp" using namespace cl::sycl; diff --git a/clang/test/Driver/aarch64-cpus.c b/clang/test/Driver/aarch64-cpus.c index c7dc5f63d6786..f1b53d98e1506 100644 --- a/clang/test/Driver/aarch64-cpus.c +++ b/clang/test/Driver/aarch64-cpus.c @@ -45,6 +45,22 @@ // ARM64-CA35: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cortex-a35" // ARM64-CA35-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" +// RUN: %clang -target aarch64 -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34 %s +// RUN: %clang -target aarch64 -mlittle-endian -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34 %s +// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34 %s +// RUN: %clang -target aarch64 -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-TUNE %s +// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-TUNE %s +// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-TUNE %s +// CA34: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a34" +// CA34-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" + +// RUN: %clang -target arm64 -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA34 %s +// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA34 %s +// RUN: %clang -target arm64 -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA34-TUNE %s +// RUN: %clang -target arm64 -mlittle-endian -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA34-TUNE %s +// ARM64-CA34: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cortex-a34" +// ARM64-CA34-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" + // RUN: %clang -target aarch64 -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53 %s // RUN: %clang -target aarch64 -mlittle-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53 %s // RUN: %clang -target aarch64_be -mlittle-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53 %s @@ -267,6 +283,15 @@ // CA35-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "cortex-a35" // CA35-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" +// RUN: %clang -target aarch64_be -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE %s +// RUN: %clang -target aarch64 -mbig-endian -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE %s +// RUN: %clang -target aarch64_be -mbig-endian -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE %s +// RUN: %clang -target aarch64_be -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE-TUNE %s +// RUN: %clang -target aarch64 -mbig-endian -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE-TUNE %s +// RUN: %clang -target aarch64_be -mbig-endian -mtune=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CA34-BE-TUNE %s +// CA34-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "cortex-a34" +// CA34-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" + // RUN: %clang -target aarch64_be -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53-BE %s // RUN: %clang -target aarch64 -mbig-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53-BE %s // RUN: %clang -target aarch64_be -mbig-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53-BE %s diff --git a/clang/test/Driver/arm-cde.c b/clang/test/Driver/arm-cde.c new file mode 100644 index 0000000000000..8dfa130da3fb2 --- /dev/null +++ b/clang/test/Driver/arm-cde.c @@ -0,0 +1,33 @@ +// RUN: %clang -target arm-none-none-eabi -march=armv8m.main %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCDE,CHECK-NOCDE-V8 +// RUN: %clang -target arm-none-none-eabi -march=armv8.1m.main %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCDE,CHECK-NOCDE-V81 +// CHECK-NOCDE-V8: "-triple" "thumbv8m.main-none-none-eabi" +// CHECK-NOCDE-V81: "-triple" "thumbv8.1m.main-none-none-eabi" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp0" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp1" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp2" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp3" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp4" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp5" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp6" +// CHECK-NOCDE-NOT: "-target-feature" "+cdecp7" + +// RUN: %clang -target arm-none-none-eabi -march=armv8m.main+cdecp0+cdecp3 %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-CDE1,CHECK-CDE1-V8 +// RUN: %clang -target arm-none-none-eabi -march=armv8.1m.main+cdecp0+cdecp3 %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-CDE1,CHECK-CDE1-V81 +// RUN: %clang -target arm-none-none-eabi -march=armv8.1m.main+mve.fp+cdecp0+cdecp3 %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-CDE1,CHECK-CDE1-V81MVE +// CHECK-CDE1-V8: "-triple" "thumbv8m.main-none-none-eabi" +// CHECK-CDE1-V81: "-triple" "thumbv8.1m.main-none-none-eabi" +// CHECK-CDE1-V81MVE: "-triple" "thumbv8.1m.main-none-none-eabi" +// CHECK-CDE1-V81MVE-DAG: "-target-feature" "+mve.fp" +// CHECK-CDE1-DAG: "-target-feature" "+cdecp0" +// CHECK-CDE1-DAG: "-target-feature" "+cdecp3" + +// RUN: %clang -target arm-none-none-eabi -march=armv8m.main+cdecp0+cdecp3 %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-CDE2,CHECK-CDE2-V8 +// RUN: %clang -target arm-none-none-eabi -march=armv8.1m.main+cdecp0+cdecp3 %s -### -c 2>&1 | FileCheck %s --check-prefixes=CHECK-CDE2,CHECK-CDE2-V81 +// CHECK-CDE2-V8: "-triple" "thumbv8m.main-none-none-eabi" +// CHECK-CDE2-V81: "-triple" "thumbv8.1m.main-none-none-eabi" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp1" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp2" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp4" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp5" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp6" +// CHECK-CDE2-NOT: "-target-feature" "+cdecp7" diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index f230caa936be1..67744d95e6e9c 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -199,10 +199,16 @@ // RUN: %clang_cl /Qvec /Qvec- -### -- %s 2>&1 | FileCheck -check-prefix=Qvec_ %s // Qvec_-NOT: -vectorize-loops -// RUN: %clang_cl /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes %s -// showIncludes: --show-includes +// RUN: %clang_cl /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_ %s +// showIncludes_: --show-includes +// showIncludes_: -sys-header-deps + +// RUN: %clang_cl /showIncludes:user -### -- %s 2>&1 | FileCheck -check-prefix=showIncludesUser %s +// showIncludesUser: --show-includes +// showIncludesUser-NOT: -sys-header-deps // RUN: %clang_cl /E /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s +// RUN: %clang_cl /E /showIncludes:user -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s // RUN: %clang_cl /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s // RUN: %clang_cl /E /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s // RUN: %clang_cl /EP /P /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index 970b4e934e78e..f628f5f40de3e 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -291,9 +291,6 @@ // RUN: -frename-registers \ // RUN: -fschedule-insns2 \ // RUN: -fsingle-precision-constant \ -// RUN: -ftree_loop_im \ -// RUN: -ftree_loop_ivcanon \ -// RUN: -ftree_loop_linear \ // RUN: -funsafe-loop-optimizations \ // RUN: -fuse-linker-plugin \ // RUN: -fvect-cost-model \ @@ -367,9 +364,6 @@ // RUN: -frename-registers \ // RUN: -fschedule-insns2 \ // RUN: -fsingle-precision-constant \ -// RUN: -ftree_loop_im \ -// RUN: -ftree_loop_ivcanon \ -// RUN: -ftree_loop_linear \ // RUN: -funsafe-loop-optimizations \ // RUN: -fuse-linker-plugin \ // RUN: -fvect-cost-model \ @@ -431,9 +425,6 @@ // CHECK-WARNING-DAG: optimization flag '-frename-registers' is not supported // CHECK-WARNING-DAG: optimization flag '-fschedule-insns2' is not supported // CHECK-WARNING-DAG: optimization flag '-fsingle-precision-constant' is not supported -// CHECK-WARNING-DAG: optimization flag '-ftree_loop_im' is not supported -// CHECK-WARNING-DAG: optimization flag '-ftree_loop_ivcanon' is not supported -// CHECK-WARNING-DAG: optimization flag '-ftree_loop_linear' is not supported // CHECK-WARNING-DAG: optimization flag '-funsafe-loop-optimizations' is not supported // CHECK-WARNING-DAG: optimization flag '-fuse-linker-plugin' is not supported // CHECK-WARNING-DAG: optimization flag '-fvect-cost-model' is not supported @@ -581,6 +572,11 @@ // CHECK-RECORD-GCC-SWITCHES: "-record-command-line" // CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line" // CHECK-RECORD-GCC-SWITCHES-ERROR: error: unsupported option '-frecord-command-line' for target +// Test when clang is in a path containing a space. +// RUN: mkdir -p "%t.r/with spaces" +// RUN: cp %clang "%t.r/with spaces/clang" +// RUN: "%t.r/with spaces/clang" -### -S -target x86_64-unknown-linux -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ESCAPED %s +// CHECK-RECORD-GCC-SWITCHES-ESCAPED: "-record-command-line" "{{.+}}with\\ spaces{{.+}}" // RUN: %clang -### -S -ftrivial-auto-var-init=uninitialized %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-UNINIT %s // RUN: %clang -### -S -ftrivial-auto-var-init=pattern %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-PATTERN %s diff --git a/clang/test/Driver/code-model.c b/clang/test/Driver/code-model.c deleted file mode 100644 index dcb54e972a507..0000000000000 --- a/clang/test/Driver/code-model.c +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clang -### -c -mcmodel=tiny %s 2>&1 | FileCheck -check-prefix CHECK-TINY %s -// RUN: %clang -### -c -mcmodel=small %s 2>&1 | FileCheck -check-prefix CHECK-SMALL %s -// RUN: %clang -### -S -mcmodel=kernel %s 2>&1 | FileCheck -check-prefix CHECK-KERNEL %s -// RUN: %clang -### -c -mcmodel=medium %s 2>&1 | FileCheck -check-prefix CHECK-MEDIUM %s -// RUN: %clang -### -S -mcmodel=large %s 2>&1 | FileCheck -check-prefix CHECK-LARGE %s -// RUN: not %clang -c -mcmodel=lager %s 2>&1 | FileCheck -check-prefix CHECK-INVALID %s - -// CHECK-TINY: "-mcode-model" "tiny" -// CHECK-SMALL: "-mcode-model" "small" -// CHECK-KERNEL: "-mcode-model" "kernel" -// CHECK-MEDIUM: "-mcode-model" "medium" -// CHECK-LARGE: "-mcode-model" "large" - -// CHECK-INVALID: error: invalid value 'lager' in '-mcode-model lager' - diff --git a/clang/test/Driver/hexagon-toolchain-elf.c b/clang/test/Driver/hexagon-toolchain-elf.c index 9b5ebe3c86a49..a0bf8cac96682 100644 --- a/clang/test/Driver/hexagon-toolchain-elf.c +++ b/clang/test/Driver/hexagon-toolchain-elf.c @@ -577,3 +577,14 @@ // RUN: | FileCheck -check-prefix=CHECK082 %s // CHECK082-NOT: -march= // CHECK082-NOT: -mcpu= +// ----------------------------------------------------------------------------- +// Passing --sysroot +// ----------------------------------------------------------------------------- +// RUN: %clang -### -target hexagon-unknown-elf \ +// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \ +// RUN: -mcpu=hexagonv60 \ +// RUN: --sysroot=/hexagon \ +// RUN: %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK083 %s +// CHECK083: "-isysroot" "/hexagon" +// CHECK083: "-internal-externc-isystem" "/hexagon{{/|\\\\}}include" diff --git a/clang/test/Driver/mbackchain.c b/clang/test/Driver/mbackchain.c index 33076829ccd7e..f0a4f86558d7d 100644 --- a/clang/test/Driver/mbackchain.c +++ b/clang/test/Driver/mbackchain.c @@ -1,3 +1,7 @@ // RUN: %clang -target s390x -c -### %s -mpacked-stack -mbackchain 2>&1 | FileCheck %s +// RUN: %clang -target s390x -c -### %s -mpacked-stack -mbackchain -msoft-float \ +// RUN: 2>&1 | FileCheck %s --check-prefix=KERNEL-BUILD +// REQUIRES: systemz-registered-target -// CHECK: error: unsupported option '-mpacked-stack -mbackchain' +// CHECK: error: unsupported option '-mpacked-stack -mbackchain -mhard-float' +// KERNEL-BUILD-NOT: error: unsupported option diff --git a/clang/test/Driver/mcmodel.c b/clang/test/Driver/mcmodel.c new file mode 100644 index 0000000000000..8df5c6a7e38be --- /dev/null +++ b/clang/test/Driver/mcmodel.c @@ -0,0 +1,14 @@ +// RUN: %clang -target x86_64 -### -c -mcmodel=tiny %s 2>&1 | FileCheck --check-prefix=TINY %s +// RUN: %clang -target x86_64 -### -c -mcmodel=small %s 2>&1 | FileCheck --check-prefix=SMALL %s +// RUN: %clang -target x86_64 -### -S -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=KERNEL %s +// RUN: %clang -target x86_64 -### -c -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=MEDIUM %s +// RUN: %clang -target x86_64 -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s +// RUN: not %clang -c -mcmodel=lager %s 2>&1 | FileCheck --check-prefix=INVALID %s + +// TINY: "-mcmodel=tiny" +// SMALL: "-mcmodel=small" +// KERNEL: "-mcmodel=kernel" +// MEDIUM: "-mcmodel=medium" +// LARGE: "-mcmodel=large" + +// INVALID: error: invalid argument 'lager' to -mcmodel= diff --git a/clang/test/Driver/mfentry.c b/clang/test/Driver/mfentry.c index ee402ea1b73d1..34ef9d9ca11b9 100644 --- a/clang/test/Driver/mfentry.c +++ b/clang/test/Driver/mfentry.c @@ -1,9 +1,19 @@ // RUN: %clang -target s390x -c -### %s -mfentry 2>&1 | FileCheck %s // RUN: %clang -target i386 -c -### %s -mfentry 2>&1 | FileCheck %s // RUN: %clang -target x86_64 -c -### %s -mfentry 2>&1 | FileCheck %s +// RUN: %clang -target x86_64-linux-gnu -pg -mfentry -O0 -### -E %s 2>&1 | FileCheck -check-prefix=FP %s +// RUN: %clang -target x86_64-linux-gnu -pg -mfentry -O2 -fno-omit-frame-pointer -### -E %s 2>&1 | FileCheck -check-prefix=FP %s +// RUN: %clang -target x86_64-linux-gnu -pg -mfentry -O2 -### -E %s 2>&1 | FileCheck -check-prefix=NOFP %s +// RUN: %clang -target x86_64 -pg -mfentry -O0 -### -E %s 2>&1 | FileCheck -check-prefix=FP %s +// RUN: %clang -target x86_64 -pg -mfentry -O2 -fno-omit-frame-pointer -### -E %s 2>&1 | FileCheck -check-prefix=FP %s +// RUN: %clang -target x86_64 -pg -mfentry -O2 -### -E %s 2>&1 | FileCheck -check-prefix=FP %s // CHECK: "-mfentry" // RUN: %clang -target powerpc64le -c -### %s -mfentry 2>&1 | FileCheck --check-prefix=ERR %s // ERR: error: unsupported option '-mfentry' for target 'powerpc64le' + +// FP: "-mframe-pointer=all" +// NOFP: "-mframe-pointer=none" +void foo(void) {} diff --git a/clang/test/Driver/riscv32-toolchain-extra.c b/clang/test/Driver/riscv32-toolchain-extra.c index ad3974bd9c789..ff9842b37c02b 100644 --- a/clang/test/Driver/riscv32-toolchain-extra.c +++ b/clang/test/Driver/riscv32-toolchain-extra.c @@ -19,6 +19,7 @@ // RUN: ln -s %S/Inputs/basic_riscv32_nogcc_tree/bin/riscv32-unknown-elf-ld %T/testroot-riscv32-baremetal-nogcc/bin/riscv32-unknown-elf-ld // RUN: ln -s %S/Inputs/basic_riscv32_nogcc_tree/riscv32-unknown-elf %T/testroot-riscv32-baremetal-nogcc/riscv32-unknown-elf // RUN: %T/testroot-riscv32-baremetal-nogcc/bin/clang %s -### -no-canonical-prefixes \ +// RUN: --gcc-toolchain=%T/testroot-riscv32-baremetal-nogcc/invalid \ // RUN: -target riscv32-unknown-elf --rtlib=platform 2>&1 \ // RUN: | FileCheck -check-prefix=C-RV32-BAREMETAL-ILP32-NOGCC %s diff --git a/clang/test/Driver/riscv64-toolchain-extra.c b/clang/test/Driver/riscv64-toolchain-extra.c index 2213d96456ec3..6b474e88f4736 100644 --- a/clang/test/Driver/riscv64-toolchain-extra.c +++ b/clang/test/Driver/riscv64-toolchain-extra.c @@ -19,6 +19,7 @@ // RUN: ln -s %S/Inputs/basic_riscv64_nogcc_tree/bin/riscv64-unknown-elf-ld %T/testroot-riscv64-baremetal-nogcc/bin/riscv64-unknown-elf-ld // RUN: ln -s %S/Inputs/basic_riscv64_nogcc_tree/riscv64-unknown-elf %T/testroot-riscv64-baremetal-nogcc/riscv64-unknown-elf // RUN: %T/testroot-riscv64-baremetal-nogcc/bin/clang %s -### -no-canonical-prefixes \ +// RUN: --gcc-toolchain=%T/testroot-riscv64-baremetal-nogcc/invalid \ // RUN: -target riscv64-unknown-elf --rtlib=platform 2>&1 \ // RUN: | FileCheck -check-prefix=C-RV64-BAREMETAL-LP64-NOGCC %s diff --git a/clang/test/Driver/unknown-std.cpp b/clang/test/Driver/unknown-std.cpp index 2122a7468d039..9ce9507567a33 100644 --- a/clang/test/Driver/unknown-std.cpp +++ b/clang/test/Driver/unknown-std.cpp @@ -15,8 +15,8 @@ // CHECK-NEXT: note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard // CHECK-NEXT: note: use 'c++17' for 'ISO C++ 2017 with amendments' standard // CHECK-NEXT: note: use 'gnu++17' for 'ISO C++ 2017 with amendments and GNU extensions' standard -// CHECK-NEXT: note: use 'c++2a' for 'Working draft for ISO C++ 2020' standard -// CHECK-NEXT: note: use 'gnu++2a' for 'Working draft for ISO C++ 2020 with GNU extensions' standard +// CHECK-NEXT: note: use 'c++20' for 'ISO C++ 2020 DIS' standard +// CHECK-NEXT: note: use 'gnu++20' for 'ISO C++ 2020 DIS with GNU extensions' standard // CUDA-NEXT: note: use 'cuda' for 'NVIDIA CUDA(tm)' standard // Make sure that no other output is present. diff --git a/clang/test/Frontend/print-header-includes.c b/clang/test/Frontend/print-header-includes.c index 7da56e23d7082..c5b711a87e008 100644 --- a/clang/test/Frontend/print-header-includes.c +++ b/clang/test/Frontend/print-header-includes.c @@ -1,32 +1,51 @@ -// RUN: %clang_cc1 -I%S -include Inputs/test3.h -E -H -o /dev/null %s 2> %t.stderr +// RUN: %clang_cc1 -I%S -include Inputs/test3.h -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: -E -H -o /dev/null %s 2> %t.stderr // RUN: FileCheck < %t.stderr %s // CHECK-NOT: test3.h +// CHECK-NOT: . {{.*noline.h}} // CHECK: . {{.*test.h}} // CHECK: .. {{.*test2.h}} -// RUN: %clang_cc1 -I%S -include Inputs/test3.h --show-includes -o /dev/null %s | \ +// RUN: %clang_cc1 -I%S -include Inputs/test3.h -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: -E -H -sys-header-deps -o /dev/null %s 2> %t.stderr +// RUN: FileCheck --check-prefix SYSHEADERS < %t.stderr %s + +// SYSHEADERS-NOT: test3.h +// SYSHEADERS: . {{.*noline.h}} +// SYSHEADERS: . {{.*test.h}} +// SYSHEADERS: .. {{.*test2.h}} + +// RUN: %clang_cc1 -I%S -include Inputs/test3.h -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: --show-includes -o /dev/null %s | \ // RUN: FileCheck --strict-whitespace --check-prefix=MS-STDOUT %s // MS-STDOUT-NOT: +// MS-STDOUT-NOT: Note: including file: {{[^ ]*noline.h}} // MS-STDOUT: Note: including file: {{[^ ]*test3.h}} // MS-STDOUT: Note: including file: {{[^ ]*test.h}} // MS-STDOUT: Note: including file: {{[^ ]*test2.h}} // MS-STDOUT-NOT: Note -// RUN: %clang_cc1 -I%S -include Inputs/test3.h -E --show-includes -o /dev/null %s 2> %t.stderr +// RUN: %clang_cc1 -I%S -include Inputs/test3.h -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: -E --show-includes -o /dev/null %s 2> %t.stderr // RUN: FileCheck --strict-whitespace --check-prefix=MS-STDERR < %t.stderr %s // MS-STDERR-NOT: +// MS-STDERR-NOT: Note: including file: {{[^ ]*noline.h}} // MS-STDERR: Note: including file: {{[^ ]*test3.h}} // MS-STDERR: Note: including file: {{[^ ]*test.h}} // MS-STDERR: Note: including file: {{[^ ]*test2.h}} // MS-STDERR-NOT: Note // RUN: echo "fun:foo" > %t.blacklist -// RUN: %clang_cc1 -I%S -fsanitize=address -fdepfile-entry=%t.blacklist --show-includes -o /dev/null %s | \ +// RUN: %clang_cc1 -I%S -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: -fsanitize=address -fdepfile-entry=%t.blacklist \ +// RUN: --show-includes -o /dev/null %s | \ // RUN: FileCheck --strict-whitespace --check-prefix=MS-BLACKLIST %s // MS-BLACKLIST: Note: including file: {{[^ ]*\.blacklist}} +// MS-BLACKLIST-NOT: Note: including file: {{[^ ]*noline.h}} // MS-BLACKLIST: Note: including file: {{[^ ]*test.h}} // MS-BLACKLIST: Note: including file: {{[^ ]*test2.h}} // MS-BLACKLIST-NOT: Note +#include #include "Inputs/test.h" diff --git a/clang/test/Index/Core/index-instantiated-source.cpp b/clang/test/Index/Core/index-instantiated-source.cpp index 7a810fbdf3a87..2a67a3a3c7938 100644 --- a/clang/test/Index/Core/index-instantiated-source.cpp +++ b/clang/test/Index/Core/index-instantiated-source.cpp @@ -86,3 +86,37 @@ void canonicalizeInstaniationReferences(TemplateClass &object) { (void)TT::NestedType::Enum::EnumCase; // CHECK: [[@LINE-1]]:31 | enumerator/C | EnumCase | c:@ST>2#T#T@TemplateClass@S@NestedType@E@Enum@EnumCase | } + +namespace index_specialization { +template +class Foo {}; + +// if there are no explicit template specializations provided, report the +// primary templates. +Foo *t1; // incomplete instantiation. +// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N@index_specialization@ST>1#T@Foo | | Ref,RelCont | rel: 1 + +Foo t2; +// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N@index_specialization@ST>1#T@Foo | | Ref,RelCont | rel: 1 + +// explicit instantiations. +template class Foo; +Foo t3; +// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | Foo | c:@N@index_specialization@ST>1#T@Foo | | Ref,RelCont | rel: 1 + + +template +class Bar {}; + +// explicit template specialization definition! +template <>class Bar {}; +// report the explicit template specialization if it exists. +Bar *b1; +// CHECK: [[@LINE-1]]:1 | class(Gen,TS)/C++ | Bar | c:@N@index_specialization@S@Bar>#I | | Ref,RelCont | rel: 1 + +// explicit template declaration, not a definition! +template <> class Bar ; +Bar *b2; +// CHECK: [[@LINE-1]]:1 | class(Gen,TS)/C++ | Bar | c:@N@index_specialization@S@Bar>#f | | Ref,RelCont | rel: 1 + +} // namespace index_specialization diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp index f159b1c884304..371265b115b2f 100644 --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -321,7 +321,7 @@ template<> void functionSp, Record::C>() { // CHECK: [[@LINE-1]]:6 | function(Gen,TS)/C++ | functionSp | c:@F@functionSp<#$@S@SpecializationDecl>#$@S@Cls#VI2># | __Z10functionSpI18SpecializationDeclI3ClsELi2EEvv | Def,RelSpecialization | rel: 1 // CHECK: RelSpecialization | functionSp | c:@FT@>2#T#NIfunctionSp#v# -// CHECK: [[@LINE-3]]:17 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#$@S@Cls | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-3]]:17 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | | Ref,RelCont | rel: 1 // CHECK: [[@LINE-4]]:36 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 // CHECK: [[@LINE-5]]:50 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,RelCont | rel: 1 // CHECK: [[@LINE-6]]:42 | struct/C++ | Record | c:@S@Record | | Ref,RelCont | rel: 1 @@ -332,7 +332,7 @@ class ClassWithCorrectSpecialization { }; template<> class ClassWithCorrectSpecialization, Record::C> { }; -// CHECK: [[@LINE-1]]:38 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#$@S@Cls | | Ref | rel: 0 +// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | | Ref | rel: 0 // CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls | | Ref | rel: 0 // CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0 // CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@Record | | Ref | rel: 0 @@ -505,7 +505,7 @@ struct Guided { T t; }; // CHECK-NEXT: [[@LINE-2]]:19 | field/C++ | t | c:@ST>1#T@Guided@FI@t | | Def,RelChild | rel: 1 // CHECK-NEXT: RelChild | Guided | c:@ST>1#T@Guided Guided(double) -> Guided; -// CHECK: [[@LINE-1]]:19 | struct(Gen,TS)/C++ | Guided | c:@S@Guided>#f | | Ref | rel: 0 +// CHECK: [[@LINE-1]]:19 | struct(Gen)/C++ | Guided | c:@ST>1#T@Guided | | Ref | rel: 0 // CHECK-NEXT: [[@LINE-2]]:1 | struct(Gen)/C++ | Guided | c:@ST>1#T@Guided | | Ref | rel: 0 auto guided = Guided{1.0}; // CHECK: [[@LINE-1]]:6 | variable/C | guided | c:@guided | _guided | Def | rel: 0 diff --git a/clang/test/Lexer/cxx2a-spaceship.cpp b/clang/test/Lexer/cxx2a-spaceship.cpp index 604575ee976b7..2163a0bf190f9 100644 --- a/clang/test/Lexer/cxx2a-spaceship.cpp +++ b/clang/test/Lexer/cxx2a-spaceship.cpp @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -std=c++17 %s -verify -// RUN: %clang_cc1 -std=c++2a %s -verify -// RUN: %clang_cc1 -std=c++2a %s -verify -Wc++17-compat -DCOMPAT +// RUN: %clang_cc1 -std=c++20 %s -verify +// RUN: %clang_cc1 -std=c++20 %s -verify -Wc++17-compat -DCOMPAT // // RUN: %clang_cc1 -std=c++17 %s -E -o - | FileCheck %s --check-prefix=CXX17 -// RUN: %clang_cc1 -std=c++2a %s -E -o - | FileCheck %s --check-prefix=CXX20 +// RUN: %clang_cc1 -std=c++20 %s -E -o - | FileCheck %s --check-prefix=CXX20 namespace N { @@ -12,19 +12,19 @@ void operator<=(A, A); #if __cplusplus > 201703L void operator<=>(A, A); #ifdef COMPAT -// expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++2a}} +// expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++20}} #endif #endif template struct X {}; X #if __cplusplus <= 201703L - // expected-warning@-2 {{'<=>' is a single token in C++2a; add a space to avoid a change in behavior}} + // expected-warning@-2 {{'<=>' is a single token in C++20; add a space to avoid a change in behavior}} #else > #endif #ifdef COMPAT -// expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++2a}} +// expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++20}} #endif x; } diff --git a/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp b/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp index a2e86931e9c03..ec42e219494c8 100644 --- a/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp +++ b/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -Wc++2a-compat -std=c++17 +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wc++20-compat -std=c++17 #define concept constexpr bool template concept x = 0; #undef concept -int co_await = 0; // expected-warning {{'co_await' is a keyword in C++2a}} -int co_return = 0; // expected-warning {{'co_return' is a keyword in C++2a}} -int co_yield = 0; // expected-warning {{'co_yield' is a keyword in C++2a}} -int char8_t = 0; // expected-warning {{'char8_t' is a keyword in C++2a}} -int concept = 0; // expected-warning {{'concept' is a keyword in C++2a}} -int requires = 0; // expected-warning {{'requires' is a keyword in C++2a}} -int consteval = 0; // expected-warning {{'consteval' is a keyword in C++2a}} -int constinit = 0; // expected-warning {{'constinit' is a keyword in C++2a}} +int co_await = 0; // expected-warning {{'co_await' is a keyword in C++20}} +int co_return = 0; // expected-warning {{'co_return' is a keyword in C++20}} +int co_yield = 0; // expected-warning {{'co_yield' is a keyword in C++20}} +int char8_t = 0; // expected-warning {{'char8_t' is a keyword in C++20}} +int concept = 0; // expected-warning {{'concept' is a keyword in C++20}} +int requires = 0; // expected-warning {{'requires' is a keyword in C++20}} +int consteval = 0; // expected-warning {{'consteval' is a keyword in C++20}} +int constinit = 0; // expected-warning {{'constinit' is a keyword in C++20}} diff --git a/clang/test/Misc/serialized-diags.c b/clang/test/Misc/serialized-diags.c index e401477a2ebdc..2f4b86fb42f95 100644 --- a/clang/test/Misc/serialized-diags.c +++ b/clang/test/Misc/serialized-diags.c @@ -56,7 +56,7 @@ void rdar11040133() { // CHECK: Range: {{.*[/\\]}}serialized-diags.c:22:13 {{.*[/\\]}}serialized-diags.c:22:18 // CHECK: +-{{.*[/\\]}}serialized-diags.c:20:15: note: expanded from macro 'false' [] // CHECK: +-Range: {{.*[/\\]}}serialized-diags.c:20:15 {{.*[/\\]}}serialized-diags.c:20:16 -// CHECK: +-{{.*[/\\]}}serialized-diags.c:19:1: note: 'taz' declared here [] +// CHECK: +-{{.*[/\\]}}serialized-diags.c:19:6: note: 'taz' declared here [] // CHECK: {{.*[/\\]}}serialized-diags.h:5:7: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion] // CHECK: Range: {{.*[/\\]}}serialized-diags.h:5:16 {{.*[/\\]}}serialized-diags.h:5:17 // CHECK: +-{{.*[/\\]}}serialized-diags.c:26:10: note: in file included from {{.*[/\\]}}serialized-diags.c:26: [] diff --git a/clang/test/OpenMP/allocate_allocator_messages.cpp b/clang/test/OpenMP/allocate_allocator_messages.cpp index fced4cae9d529..0c4d36fc5f569 100644 --- a/clang/test/OpenMP/allocate_allocator_messages.cpp +++ b/clang/test/OpenMP/allocate_allocator_messages.cpp @@ -28,7 +28,7 @@ extern const omp_allocator_handle_t omp_thread_mem_alloc; struct St1{ int a; static int b; -#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'const omp_allocator_handle_t' (aka 'void **const') with an expression of incompatible type 'int'}} expected-note {{previous allocator is specified here}} +#pragma omp allocate(b) allocator(sss) // expected-error {{incompatible integer to pointer conversion initializing 'const omp_allocator_handle_t' (aka 'void **const') with an expression of type 'int'}} expected-note {{previous allocator is specified here}} #pragma omp allocate(b) #pragma omp allocate(b) allocator(omp_thread_mem_alloc) // expected-warning {{allocate directive specifies 'omp_thread_mem_alloc' allocator while previously used default}} } d; // expected-note 2 {{'d' defined here}} diff --git a/clang/test/OpenMP/cancel_codegen.cpp b/clang/test/OpenMP/cancel_codegen.cpp index 8402f0fef0df7..b7d1cea56721f 100644 --- a/clang/test/OpenMP/cancel_codegen.cpp +++ b/clang/test/OpenMP/cancel_codegen.cpp @@ -193,11 +193,9 @@ for (int i = 0; i < argc; ++i) { // IRBUILDER: br i1 [[CMP]], label %[[CONTINUE:[^,].+]], label %[[EXIT:.+]] // IRBUILDER: [[EXIT]] // IRBUILDER: br label %[[EXIT2:.+]] -// IRBUILDER: [[EXIT2]] -// IRBUILDER: br label %[[EXIT3:.+]] // IRBUILDER: [[CONTINUE]] // IRBUILDER: br label %[[ELSE:.+]] -// IRBUILDER: [[EXIT3]] +// IRBUILDER: [[EXIT2]] // IRBUILDER: br label %[[RETURN]] #endif diff --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp index 1a371d699789f..cc6558debde6d 100644 --- a/clang/test/OpenMP/declare_target_messages.cpp +++ b/clang/test/OpenMP/declare_target_messages.cpp @@ -162,17 +162,17 @@ namespace { #pragma omp declare target link(x) // expected-error {{'x' must not appear in both clauses 'to' and 'link'}} void bazz() {} -#pragma omp declare target to(bazz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} host5-note 3{{marked as 'device_type(nohost)' here}} +#pragma omp declare target to(bazz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} host5-note {{marked as 'device_type(nohost)' here}} void bazzz() {bazz();} #pragma omp declare target to(bazzz) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} void any() {bazz();} // host5-error {{function with 'device_type(nohost)' is not available on host}} -void host1() {bazz();} // host5-error {{function with 'device_type(nohost)' is not available on host}} -#pragma omp declare target to(host1) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} dev5-note 4 {{marked as 'device_type(host)' here}} -void host2() {bazz();} //host5-error {{function with 'device_type(nohost)' is not available on host}} +void host1() {bazz();} +#pragma omp declare target to(host1) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} dev5-note 2 {{marked as 'device_type(host)' here}} +void host2() {bazz();} #pragma omp declare target to(host2) -void device() {host1();} // dev5-error {{function with 'device_type(host)' is not available on device}} +void device() {host1();} #pragma omp declare target to(device) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} host5-note 2 {{marked as 'device_type(nohost)' here}} -void host3() {host1();} // dev5-error {{function with 'device_type(host)' is not available on device}} +void host3() {host1();} #pragma omp declare target to(host3) #pragma omp declare target diff --git a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp index faff77e0a43b7..433ba13f73d60 100644 --- a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp +++ b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp @@ -38,7 +38,7 @@ int d; #pragma omp end declare target int c; -int bar() { return 1 + foo() + bar() + baz1() + baz2(); } // expected-note {{called by 'bar'}} +int bar() { return 1 + foo() + bar() + baz1() + baz2(); } int maini1() { int a; @@ -49,7 +49,7 @@ int maini1() { { S s(a); static long aaa = 23; - a = foo() + bar() + b + c + d + aa + aaa + FA(); // expected-note{{called by 'maini1'}} + a = foo() + bar() + b + c + d + aa + aaa + FA(); if (!a) throw "Error"; // expected-error {{cannot use 'throw' with exceptions disabled}} } diff --git a/clang/test/OpenMP/parallel_codegen.cpp b/clang/test/OpenMP/parallel_codegen.cpp index f96ad406c25f1..586187f095214 100644 --- a/clang/test/OpenMP/parallel_codegen.cpp +++ b/clang/test/OpenMP/parallel_codegen.cpp @@ -60,8 +60,7 @@ int main (int argc, char **argv) { // ALL-DEBUG-LABEL: define i32 @main(i32 %argc, i8** %argv) // CHECK-DEBUG: [[LOC_2_ADDR:%.+]] = alloca %struct.ident_t // CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[LOC_2_ADDR]] to i8* -// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[DEF_LOC_2]] to i8* -// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i1 false) +// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 bitcast (%struct.ident_t* [[DEF_LOC_2]] to i8*), i64 24, i1 false) // ALL-DEBUG: store i32 %argc, i32* [[ARGC_ADDR:%.+]], // ALL-DEBUG: [[VLA:%.+]] = alloca i32, i64 [[VLA_SIZE:%[^,]+]], // CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %struct.ident_t, %struct.ident_t* [[LOC_2_ADDR]], i32 0, i32 4 @@ -118,8 +117,7 @@ int main (int argc, char **argv) { // ALL-DEBUG: define linkonce_odr i32 [[TMAIN]](i8** %argc) // CHECK-DEBUG-DAG: [[LOC_2_ADDR:%.+]] = alloca %struct.ident_t // CHECK-DEBUG: [[KMPC_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[LOC_2_ADDR]] to i8* -// CHECK-DEBUG-NEXT: [[KMPC_DEFAULT_LOC_VOIDPTR:%.+]] = bitcast %struct.ident_t* [[DEF_LOC_2]] to i8* -// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 [[KMPC_DEFAULT_LOC_VOIDPTR]], i64 24, i1 false) +// CHECK-DEBUG-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[KMPC_LOC_VOIDPTR]], i8* align 8 bitcast (%struct.ident_t* [[DEF_LOC_2]] to i8*), i64 24, i1 false) // CHECK-DEBUG-NEXT: store i8** %argc, i8*** [[ARGC_ADDR:%.+]], // CHECK-DEBUG: [[KMPC_LOC_PSOURCE_REF:%.+]] = getelementptr inbounds %struct.ident_t, %struct.ident_t* [[LOC_2_ADDR]], i32 0, i32 4 // CHECK-DEBUG-NEXT: store i8* getelementptr inbounds ([{{.+}} x i8], [{{.+}} x i8]* [[LOC2]], i32 0, i32 0), i8** [[KMPC_LOC_PSOURCE_REF]] diff --git a/clang/test/OpenMP/target_firstprivate_codegen.cpp b/clang/test/OpenMP/target_firstprivate_codegen.cpp index 0b5f5f9b2b172..b90ab42f5ae2c 100644 --- a/clang/test/OpenMP/target_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_firstprivate_codegen.cpp @@ -336,9 +336,8 @@ int foo(int n, double *ptr) { } // CHECK: [[PTR_ADDR_REF:%.+]] = load double*, double** [[PTR_ADDR]], - // CHECK: [[FP_E_BC:%.+]] = bitcast [[TTII]]* [[FP_E]] to i8* // CHECK: [[E_BC:%.+]] = bitcast [[TTII]]* [[E:%.+]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{64|32}}(i8* {{.*}} [[FP_E_BC]], i8* {{.*}} [[E_BC]], i{{64|32}} 8, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{64|32}}(i8* {{.*}} bitcast ([[TTII]]* [[FP_E]] to i8*), i8* {{.*}} [[E_BC]], i{{64|32}} 8, i1 false) // CHECK: [[BASE_PTR_GEP3_0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BASE_PTR_ARR3]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTR_GEP3_0]] to double** // CHECK: store double* [[PTR_ADDR_REF]], double** [[BCAST_TOPTR]], diff --git a/clang/test/OpenMP/target_messages.cpp b/clang/test/OpenMP/target_messages.cpp index ad04e9306cb0b..5bba976b9f9f6 100644 --- a/clang/test/OpenMP/target_messages.cpp +++ b/clang/test/OpenMP/target_messages.cpp @@ -50,6 +50,12 @@ class S { int b; #pragma omp target map(this[1]) // expected-note {{expected 'this' subscript expression on map clause to be 'this[0]'}} // expected-error {{invalid 'this' expression on 'map' clause}} int c; + #pragma omp target map(foo) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + int d; + #pragma omp target map(zee) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + int e; + #pragma omp target map(this->zee) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + int f; } }; @@ -110,6 +116,14 @@ int main(int argc, char **argv) { #pragma omp target for (int n = 0; n < 100; ++n) {} + #pragma omp target map(foo) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + {} + + S s; + + #pragma omp target map(s.zee) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} + {} + return 0; } diff --git a/clang/test/Parser/asm-goto.c b/clang/test/Parser/asm-goto.c index 7f8edb1115631..f9ad6c5ee9a40 100644 --- a/clang/test/Parser/asm-goto.c +++ b/clang/test/Parser/asm-goto.c @@ -4,13 +4,13 @@ #if !__has_extension(gnu_asm) #error Extension 'gnu_asm' should be available by default #endif - +#if !__has_extension(gnu_asm_goto_with_outputs) +#error Extension 'gnu_asm_goto_with_outputs' should be available by default +#endif int a, b, c, d, e, f, g, h, i, j, k, l; -void -fgoto1 (void) -{ +void test(void) { __asm__ volatile goto ("" :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d), [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h), @@ -20,9 +20,7 @@ lab1: return; lab2: return; } -void -fgoto2 (void) -{ +void test2(void) { __asm__ volatile goto ("" :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d), [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h), @@ -31,14 +29,33 @@ fgoto2 (void) lab: return; } -int zoo () -{ +int test3(int x) { + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x) : "m" (x) : "memory" : a); +a: + return -x; +} + +int test4(int x) { + int y; + if (x > 42) + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x), "=r" (y) : "m" (x) : "memory" : a); + else + __asm__ volatile goto ("decl %0; jnz %l[b]" + : "=r" (x), "=r" (y) : "m" (x) : "memory" : b); + x = y + 42; +a: + return -x; +b: + return +x; +} + +int test5(void) { int x,cond,*e; // expected-error@+1 {{expected ')'}} asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} + // expected-error@+1 {{expected identifier}} asm goto ("decl %0;" :: "m"(x) : "memory" : ); // expected-error@+1 {{expected ':'}} asm goto ("decl %0;" :: "m"(x) : "memory" ); @@ -55,3 +72,25 @@ int zoo () loop: return 0; } + +int test6(int y) { + int x,cond,*e; + // expected-error@+1 {{expected ')'}} + asm ("mov %[e], %[e]" : "=r" (y) : [e] "rm" (*e), "r" (y) :: a) + // expected-error@+1 {{expected identifier}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" :); + // expected-error@+1 {{expected ':'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory"); + // expected-error@+1 {{use of undeclared label 'x'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : x); + // expected-error@+1 {{use of undeclared label 'b'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : b); + // expected-error@+1 {{invalid operand number in inline asm string}} + asm goto ("testl %0, %0; jne %l5;" : "=r" (y) : "r" (cond), "r" (y) :: label_true, loop); + // expected-error@+1 {{unknown symbolic operand name in inline assembly string}} + asm goto ("decl %0; jnz %l[b]" : "=r" (y) : "m" (x), "r" (y) : "memory" : a); +label_true: +loop: +a: + return 0; +} diff --git a/clang/test/Parser/asm-goto.cpp b/clang/test/Parser/asm-goto.cpp index f09466ca488d4..faff6113cad6f 100644 --- a/clang/test/Parser/asm-goto.cpp +++ b/clang/test/Parser/asm-goto.cpp @@ -1,14 +1,54 @@ // RUN: %clang_cc1 -triple i386-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s -int zoo () -{ +int a, b, c, d, e, f, g, h, i, j, k, l; + +void test1(void) { + __asm__ volatile goto ("" + :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d), + [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h), + [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l) + ::lab1,lab2); +lab1: return; +lab2: return; +} + +void test2(void) { + __asm__ volatile goto ("" + :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d), + [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h), + [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l) + :: lab); + lab: return; +} + +int test3(int x) { + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x) : "m" (x) : "memory" : a); +a: + return -x; +} + +int test4(int x) { + int y; + if (x > 42) + __asm__ volatile goto ("decl %0; jnz %l[a]" + : "=r" (x), "=r" (y) : "m" (x) : "memory" : a); + else + __asm__ volatile goto ("decl %0; jnz %l[b]" + : "=r" (x), "=r" (y) : "m" (x) : "memory" : b); + x = y + 42; +a: + return -x; +b: + return +x; +} + +int test5(void) { int x,cond,*e; // expected-error@+1 {{expected ')'}} asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} + // expected-error@+1 {{expected identifier}} asm goto ("decl %0;" :: "m"(x) : "memory" : ); // expected-error@+1 {{expected ':'}} asm goto ("decl %0;" :: "m"(x) : "memory" ); @@ -26,28 +66,24 @@ int zoo () return 0; } - -int a, b, c, d, e, f, g, h, i, j, k, l; - -void -fgoto1 (void) -{ - __asm__ volatile goto ("" - :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d), - [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h), - [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l) - ::lab1,lab2); -lab1: return; -lab2: return; -} - -void -fgoto2 (void) -{ - __asm__ volatile goto ("" - :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d), - [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h), - [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l) - :: lab); - lab: return; +int test6(int y) { + int x,cond,*e; + // expected-error@+1 {{expected ')'}} + asm ("mov %[e], %[e]" : "=r" (y) : [e] "rm" (*e), "r" (y) :: a) + // expected-error@+1 {{expected identifier}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" :); + // expected-error@+1 {{expected ':'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory"); + // expected-error@+1 {{use of undeclared label 'x'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : x); + // expected-error@+1 {{use of undeclared label 'b'}} + asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : b); + // expected-error@+1 {{invalid operand number in inline asm string}} + asm goto ("testl %0, %0; jne %l5;" : "=r" (y) : "r" (cond), "r" (y) :: label_true, loop); + // expected-error@+1 {{unknown symbolic operand name in inline assembly string}} + asm goto ("decl %0; jnz %l[b]" : "=r" (y) : "m" (x), "r" (y) : "memory" : a); +label_true: +loop: +a: + return 0; } diff --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp index 02857e21f7c3e..6203db2fbd228 100644 --- a/clang/test/Parser/cxx-ambig-decl-expr.cpp +++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp @@ -38,4 +38,7 @@ void arr() { // These are array declarations. int(x[(1,1)]); // expected-error {{redefinition}} int(x[true ? 1,1 : 1]); // expected-error {{redefinition}} + + int (*_Atomic atomic_ptr_to_int); + *atomic_ptr_to_int = 42; } diff --git a/clang/test/Parser/cxx-attributes.cpp b/clang/test/Parser/cxx-attributes.cpp index 6591532a91a20..53b098b6260ac 100644 --- a/clang/test/Parser/cxx-attributes.cpp +++ b/clang/test/Parser/cxx-attributes.cpp @@ -22,3 +22,15 @@ namespace PR17666 { } __attribute((typename)) int x; // expected-warning {{unknown attribute 'typename' ignored}} + +void fn() { + void (*__attribute__((attr)) fn_ptr)() = &fn; // expected-warning{{unknown attribute 'attr' ignored}} + void (*__attribute__((attrA)) *__attribute__((attrB)) fn_ptr_ptr)() = &fn_ptr; // expected-warning{{unknown attribute 'attrA' ignored}} expected-warning{{unknown attribute 'attrB' ignored}} + + void (&__attribute__((attr)) fn_lref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}} + void (&&__attribute__((attr)) fn_rref)() = fn; // expected-warning{{unknown attribute 'attr' ignored}} + + int i[5]; + int (*__attribute__((attr(i[1]))) pi); // expected-warning{{unknown attribute 'attr' ignored}} + pi = &i[0]; +} diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index ccd77064a2342..b791870eedaef 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions -// RUN: not %clang_cc1 -std=c++1z %s -emit-llvm-only -fcxx-exceptions +// RUN: %clang_cc1 -std=c++17 %s -verify -fcxx-exceptions +// RUN: not %clang_cc1 -std=c++17 %s -emit-llvm-only -fcxx-exceptions struct S { int a, b, c; }; @@ -67,8 +67,8 @@ namespace BadSpecifiers { struct S { int n; } s; void f() { // storage-class-specifiers - static auto &[a] = n; // expected-warning {{declared 'static' is a C++2a extension}} - thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++2a extension}} + static auto &[a] = n; // expected-warning {{declared 'static' is a C++20 extension}} + thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++20 extension}} extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}} struct S { mutable auto &[d] = n; // expected-error {{not permitted in this context}} @@ -85,7 +85,7 @@ namespace BadSpecifiers { } static constexpr inline thread_local auto &[j1] = n; // expected-error {{cannot be declared with 'constexpr inline' specifiers}} - static thread_local auto &[j2] = n; // expected-warning {{declared with 'static thread_local' specifiers is a C++2a extension}} + static thread_local auto &[j2] = n; // expected-warning {{declared with 'static thread_local' specifiers is a C++20 extension}} inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}} diff --git a/clang/test/Parser/cxx2a-concept-declaration.cpp b/clang/test/Parser/cxx2a-concept-declaration.cpp index ed88fce17c760..a7c69c29dd699 100644 --- a/clang/test/Parser/cxx2a-concept-declaration.cpp +++ b/clang/test/Parser/cxx2a-concept-declaration.cpp @@ -1,6 +1,6 @@ // Support parsing of concepts -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++20 -verify %s template concept C1 = true; // expected-note 2{{previous}} template concept C1 = true; // expected-error{{redefinition}} @@ -50,7 +50,7 @@ template concept C6 = integral_constant::value; // expected-note@-2{{'word' declared here}} template concept bool C7 = true; -// expected-warning@-1{{ISO C++2a does not permit the 'bool' keyword after 'concept'}} +// expected-warning@-1{{ISO C++20 does not permit the 'bool' keyword after 'concept'}} template<> concept C8 = false; // expected-error@-1{{concept template parameter list must have at least one parameter; explicit specialization of concepts is not allowed}} diff --git a/clang/test/Parser/cxx2a-inline-nested-namespace-definition.cpp b/clang/test/Parser/cxx2a-inline-nested-namespace-definition.cpp index 660287c83fcab..f37dc8c033cec 100644 --- a/clang/test/Parser/cxx2a-inline-nested-namespace-definition.cpp +++ b/clang/test/Parser/cxx2a-inline-nested-namespace-definition.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a -Wc++17-compat +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++20 -Wc++17-compat namespace inline foo1::foo2::foo3 { // expected-error {{expected identifier or '{'}} expected-error {{use of undeclared identifier 'foo1'}} } @@ -10,11 +10,11 @@ inline namespace foo4::foo5::foo6 { // expected-error {{nested namespace definit #if __cplusplus <= 201402L // expected-warning@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}} -// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}} +// expected-warning@+6 {{inline nested namespace definition is a C++20 extension}} #elif __cplusplus <= 201703L -// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}} +// expected-warning@+4 {{inline nested namespace definition is a C++20 extension}} #else -// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}} +// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++20}} #endif namespace valid1::valid2::inline valid3::inline valid4::valid5 {} // expected-note@-1 2 {{previous definition is here}} @@ -27,11 +27,11 @@ namespace valid1::valid2::valid3::valid4::valid5 {} #if __cplusplus <= 201402L // expected-warning@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}} -// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}} +// expected-warning@+6 {{inline nested namespace definition is a C++20 extension}} #elif __cplusplus <= 201703L -// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}} +// expected-warning@+4 {{inline nested namespace definition is a C++20 extension}} #else -// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}} +// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++20}} #endif namespace valid1::valid2::inline valid3::inline valid4::valid5 {} // expected-note@-1 2 {{previous definition is here}} diff --git a/clang/test/Parser/explicit-bool.cpp b/clang/test/Parser/explicit-bool.cpp index bdd91dbbafc92..aa700bcfd28a6 100644 --- a/clang/test/Parser/explicit-bool.cpp +++ b/clang/test/Parser/explicit-bool.cpp @@ -1,18 +1,18 @@ -// RUN: %clang_cc1 -std=c++17 -verify=cxx17 -Wc++2a-compat %s -// RUN: %clang_cc1 -std=c++2a -verify=cxx2a -Wc++17-compat %s +// RUN: %clang_cc1 -std=c++17 -verify=cxx17 -Wc++20-compat %s +// RUN: %clang_cc1 -std=c++20 -verify=cxx20 -Wc++17-compat %s namespace disambig { // Cases that are valid in C++17 and before, ill-formed in C++20, and that we // should not treat as explicit(bool) as an extension. -struct A { // cxx2a-note +{{}} +struct A { // cxx20-note +{{}} constexpr A() {} constexpr operator bool() { return true; } constexpr explicit (A)(int); // #1 // cxx17-warning@#1 {{will be parsed as explicit(bool)}} - // cxx2a-error@#1 +{{}} cxx2a-note@#1 +{{}} - // cxx2a-warning@#1 {{incompatible with C++ standards before C++2a}} + // cxx20-error@#1 +{{}} cxx20-note@#1 +{{}} + // cxx20-warning@#1 {{incompatible with C++ standards before C++20}} // This is ill-formed (via a DR change), and shouldn't be recognized as a // constructor (the function declarator cannot be parenthesized in a @@ -21,19 +21,19 @@ struct A { // cxx2a-note +{{}} // FIXME: Produce an ExtWarn for this. constexpr explicit (A(float)); // #1b // cxx17-warning@#1b {{will be parsed as explicit(bool)}} - // cxx2a-error@#1b +{{}} - // cxx2a-warning@#1b {{incompatible with C++ standards before C++2a}} + // cxx20-error@#1b +{{}} + // cxx20-warning@#1b {{incompatible with C++ standards before C++20}} explicit (operator int)(); // #2 // cxx17-warning@#2 {{will be parsed as explicit(bool)}} - // cxx2a-error@#2 +{{}} - // cxx2a-warning@#2 {{incompatible with C++ standards before C++2a}} + // cxx20-error@#2 +{{}} + // cxx20-warning@#2 {{incompatible with C++ standards before C++20}} explicit (A::operator float)(); // #2b // cxx17-warning@#2b {{will be parsed as explicit(bool)}} // cxx17-error@#2b {{extra qualification on member}} - // cxx2a-error@#2b +{{}} - // cxx2a-warning@#2b {{incompatible with C++ standards before C++2a}} + // cxx20-error@#2b +{{}} + // cxx20-warning@#2b {{incompatible with C++ standards before C++20}} }; constexpr bool operator+(A) { return true; } @@ -45,18 +45,18 @@ constexpr bool C = false; struct B { // Looks like a constructor, but not the constructor of B. explicit (A()) B(); // #3 - // cxx17-warning@#3 {{C++2a extension}} - // cxx2a-warning@#3 {{incompatible with C++ standards before C++2a}} + // cxx17-warning@#3 {{C++20 extension}} + // cxx20-warning@#3 {{incompatible with C++ standards before C++20}} // Looks like a 'constructor' of C. Actually a constructor of B. explicit (C)(B)(A); // #4 - // cxx17-warning@#4 {{C++2a extension}} - // cxx2a-warning@#4 {{incompatible with C++ standards before C++2a}} + // cxx17-warning@#4 {{C++20 extension}} + // cxx20-warning@#4 {{incompatible with C++ standards before C++20}} explicit (operator+(A())) operator int(); // #5 // cxx17-error@#5 {{requires a type specifier}} cxx17-error@#5 {{expected ';'}} // cxx17-warning@#5 {{will be parsed as explicit(bool)}} - // cxx2a-warning@#5 {{incompatible with C++ standards before C++2a}} + // cxx20-warning@#5 {{incompatible with C++ standards before C++20}} }; } diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 6d2225d1bdda7..9fb8dcecb9c0d 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -40,9 +40,6 @@ // CHECK-NOT: __ARM_FEATURE_SVE // CHECK-NOT: __ARM_FEATURE_DOTPROD -// RUN: %clang -target aarch64_be-eabi -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-BIGENDIAN -// CHECK-BIGENDIAN: __ARM_BIG_ENDIAN 1 - // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+crypto -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-CRYPTO %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+crypto -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-CRYPTO %s // CHECK-CRYPTO: __ARM_FEATURE_CRYPTO 1 @@ -152,6 +149,7 @@ // RUN: %clang -target aarch64 -mcpu=apple-s4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s // RUN: %clang -target aarch64 -mcpu=apple-s5 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s // RUN: %clang -target aarch64 -mcpu=cyclone -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s +// RUN: %clang -target aarch64 -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A34 %s // RUN: %clang -target aarch64 -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A35 %s // RUN: %clang -target aarch64 -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A53 %s // RUN: %clang -target aarch64 -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A57 %s @@ -166,6 +164,7 @@ // CHECK-MCPU-APPLE-A10: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+rdm" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes" // CHECK-MCPU-APPLE-A11: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes" // CHECK-MCPU-APPLE-A12: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.3a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes" +// CHECK-MCPU-A34: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" // CHECK-MCPU-APPLE-A13: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.4a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+fp16fml" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes" // CHECK-MCPU-A35: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" // CHECK-MCPU-A53: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" diff --git a/clang/test/Preprocessor/headermap-rel2.c b/clang/test/Preprocessor/headermap-rel2.c index 83e89f0a492eb..611ddd8356a1d 100644 --- a/clang/test/Preprocessor/headermap-rel2.c +++ b/clang/test/Preprocessor/headermap-rel2.c @@ -1,7 +1,10 @@ // RUN: rm -f %t.hmap // RUN: %hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out + +// RUN: %clang -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// RUN: FileCheck %s -input-file %t.out + +// RUN: env CC_PRINT_HEADERS=1 %clang -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/clang/test/Preprocessor/hexagon-predefines.c b/clang/test/Preprocessor/hexagon-predefines.c index fd33a66671702..5be8b96e290dc 100644 --- a/clang/test/Preprocessor/hexagon-predefines.c +++ b/clang/test/Preprocessor/hexagon-predefines.c @@ -96,3 +96,8 @@ // CHECK-V67HVX-128B: #define __HVX_LENGTH__ 128 // CHECK-V67HVX-128B: #define __HVX__ 1 // CHECK-V67HVX-128B: #define __hexagon__ 1 + +// RUN: %clang_cc1 -E -dM -triple hexagon-unknown-elf -target-cpu hexagonv67 \ +// RUN: -target-feature +hvxv67 -target-feature +hvx-length128b %s | FileCheck \ +// RUN: %s -check-prefix CHECK-ELF +// CHECK-ELF: #define __ELF__ 1 diff --git a/clang/test/Preprocessor/init-aarch64.c b/clang/test/Preprocessor/init-aarch64.c new file mode 100644 index 0000000000000..380e5e2d72618 --- /dev/null +++ b/clang/test/Preprocessor/init-aarch64.c @@ -0,0 +1,701 @@ +// RUN: %clang_cc1 -E -dM -triple=aarch64 -xc /dev/null > %t.aarch64 +// RUN: FileCheck --check-prefixes=AARCH64,AARCH64_LE,AARCH64_C %s --match-full-lines < %t.aarch64 +// RUN: %clang_cc1 -E -dM -triple=arm64 -xc /dev/null > %t.arm64 +// RUN: cmp %t.aarch64 %t.arm64 +// RUN: %clang_cc1 -E -dM -triple=aarch64_be -xc /dev/null | FileCheck --check-prefixes=AARCH64,AARCH64_BE,AARCH64_C --match-full-lines %s +// RUN: %clang_cc1 -E -dM -triple=arm64 -xc++ /dev/null | FileCheck --check-prefixes=AARCH64,AARCH64_LE,AARCH64_CXX --match-full-lines %s + +// AARCH64: #define _LP64 1 +// AARCH64_BE-NEXT: #define __AARCH64EB__ 1 +// AARCH64_BE-NEXT: #define __AARCH64_CMODEL_SMALL__ 1 +// AARCH64_BE-NEXT: #define __AARCH_BIG_ENDIAN 1 +// AARCH64_LE-NEXT: #define __AARCH64EL__ 1 +// AARCH64_LE-NEXT: #define __AARCH64_CMODEL_SMALL__ 1 +// AARCH64-NEXT: #define __ARM_64BIT_STATE 1 +// AARCH64-NEXT: #define __ARM_ACLE 200 +// AARCH64-NEXT: #define __ARM_ALIGN_MAX_STACK_PWR 4 +// AARCH64-NEXT: #define __ARM_ARCH 8 +// AARCH64-NEXT: #define __ARM_ARCH_ISA_A64 1 +// AARCH64-NEXT: #define __ARM_ARCH_PROFILE 'A' +// AARCH64_BE-NEXT: #define __ARM_BIG_ENDIAN 1 +// AARCH64-NEXT: #define __ARM_FEATURE_CLZ 1 +// AARCH64-NEXT: #define __ARM_FEATURE_DIRECTED_ROUNDING 1 +// AARCH64-NEXT: #define __ARM_FEATURE_DIV 1 +// AARCH64-NEXT: #define __ARM_FEATURE_FMA 1 +// AARCH64-NEXT: #define __ARM_FEATURE_IDIV 1 +// AARCH64-NEXT: #define __ARM_FEATURE_LDREX 0xF +// AARCH64-NEXT: #define __ARM_FEATURE_NUMERIC_MAXMIN 1 +// AARCH64-NEXT: #define __ARM_FEATURE_UNALIGNED 1 +// AARCH64-NEXT: #define __ARM_FP 0xE +// AARCH64-NEXT: #define __ARM_FP16_ARGS 1 +// AARCH64-NEXT: #define __ARM_FP16_FORMAT_IEEE 1 +// AARCH64-NEXT: #define __ARM_PCS_AAPCS64 1 +// AARCH64-NEXT: #define __ARM_SIZEOF_MINIMAL_ENUM 4 +// AARCH64-NEXT: #define __ARM_SIZEOF_WCHAR_T 4 +// AARCH64-NEXT: #define __ATOMIC_ACQUIRE 2 +// AARCH64-NEXT: #define __ATOMIC_ACQ_REL 4 +// AARCH64-NEXT: #define __ATOMIC_CONSUME 1 +// AARCH64-NEXT: #define __ATOMIC_RELAXED 0 +// AARCH64-NEXT: #define __ATOMIC_RELEASE 3 +// AARCH64-NEXT: #define __ATOMIC_SEQ_CST 5 +// AARCH64: #define __BIGGEST_ALIGNMENT__ 16 +// AARCH64_BE-NEXT: #define __BIG_ENDIAN__ 1 +// AARCH64_BE-NEXT: #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ +// AARCH64_LE-NEXT: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +// AARCH64-NEXT: #define __CHAR16_TYPE__ unsigned short +// AARCH64-NEXT: #define __CHAR32_TYPE__ unsigned int +// AARCH64-NEXT: #define __CHAR_BIT__ 8 +// AARCH64-NEXT: #define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// AARCH64-NEXT: #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 +// AARCH64-NEXT: #define __CONSTANT_CFSTRINGS__ 1 +// AARCH64-NEXT: #define __DBL_DECIMAL_DIG__ 17 +// AARCH64-NEXT: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +// AARCH64-NEXT: #define __DBL_DIG__ 15 +// AARCH64-NEXT: #define __DBL_EPSILON__ 2.2204460492503131e-16 +// AARCH64-NEXT: #define __DBL_HAS_DENORM__ 1 +// AARCH64-NEXT: #define __DBL_HAS_INFINITY__ 1 +// AARCH64-NEXT: #define __DBL_HAS_QUIET_NAN__ 1 +// AARCH64-NEXT: #define __DBL_MANT_DIG__ 53 +// AARCH64-NEXT: #define __DBL_MAX_10_EXP__ 308 +// AARCH64-NEXT: #define __DBL_MAX_EXP__ 1024 +// AARCH64-NEXT: #define __DBL_MAX__ 1.7976931348623157e+308 +// AARCH64-NEXT: #define __DBL_MIN_10_EXP__ (-307) +// AARCH64-NEXT: #define __DBL_MIN_EXP__ (-1021) +// AARCH64-NEXT: #define __DBL_MIN__ 2.2250738585072014e-308 +// AARCH64-NEXT: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ +// AARCH64-NEXT: #define __ELF__ 1 +// AARCH64-NEXT: #define __FINITE_MATH_ONLY__ 0 +// AARCH64-NEXT: #define __FLT16_DECIMAL_DIG__ 5 +// AARCH64-NEXT: #define __FLT16_DENORM_MIN__ 5.9604644775390625e-8F16 +// AARCH64-NEXT: #define __FLT16_DIG__ 3 +// AARCH64-NEXT: #define __FLT16_EPSILON__ 9.765625e-4F16 +// AARCH64-NEXT: #define __FLT16_HAS_DENORM__ 1 +// AARCH64-NEXT: #define __FLT16_HAS_INFINITY__ 1 +// AARCH64-NEXT: #define __FLT16_HAS_QUIET_NAN__ 1 +// AARCH64-NEXT: #define __FLT16_MANT_DIG__ 11 +// AARCH64-NEXT: #define __FLT16_MAX_10_EXP__ 4 +// AARCH64-NEXT: #define __FLT16_MAX_EXP__ 16 +// AARCH64-NEXT: #define __FLT16_MAX__ 6.5504e+4F16 +// AARCH64-NEXT: #define __FLT16_MIN_10_EXP__ (-4) +// AARCH64-NEXT: #define __FLT16_MIN_EXP__ (-13) +// AARCH64-NEXT: #define __FLT16_MIN__ 6.103515625e-5F16 +// AARCH64-NEXT: #define __FLT_DECIMAL_DIG__ 9 +// AARCH64-NEXT: #define __FLT_DENORM_MIN__ 1.40129846e-45F +// AARCH64-NEXT: #define __FLT_DIG__ 6 +// AARCH64-NEXT: #define __FLT_EPSILON__ 1.19209290e-7F +// AARCH64-NEXT: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-NEXT: #define __FLT_HAS_DENORM__ 1 +// AARCH64-NEXT: #define __FLT_HAS_INFINITY__ 1 +// AARCH64-NEXT: #define __FLT_HAS_QUIET_NAN__ 1 +// AARCH64-NEXT: #define __FLT_MANT_DIG__ 24 +// AARCH64-NEXT: #define __FLT_MAX_10_EXP__ 38 +// AARCH64-NEXT: #define __FLT_MAX_EXP__ 128 +// AARCH64-NEXT: #define __FLT_MAX__ 3.40282347e+38F +// AARCH64-NEXT: #define __FLT_MIN_10_EXP__ (-37) +// AARCH64-NEXT: #define __FLT_MIN_EXP__ (-125) +// AARCH64-NEXT: #define __FLT_MIN__ 1.17549435e-38F +// AARCH64-NEXT: #define __FLT_RADIX__ 2 +// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 +// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 +// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 +// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 +// AARCH64_CXX-NEXT: #define __GLIBCXX_BITSIZE_INT_N_0 128 +// AARCH64_CXX-NEXT: #define __GLIBCXX_TYPE_INT_N_0 __int128 +// AARCH64-NEXT: #define __INT16_C_SUFFIX__ +// AARCH64-NEXT: #define __INT16_FMTd__ "hd" +// AARCH64-NEXT: #define __INT16_FMTi__ "hi" +// AARCH64-NEXT: #define __INT16_MAX__ 32767 +// AARCH64-NEXT: #define __INT16_TYPE__ short +// AARCH64-NEXT: #define __INT32_C_SUFFIX__ +// AARCH64-NEXT: #define __INT32_FMTd__ "d" +// AARCH64-NEXT: #define __INT32_FMTi__ "i" +// AARCH64-NEXT: #define __INT32_MAX__ 2147483647 +// AARCH64-NEXT: #define __INT32_TYPE__ int +// AARCH64-NEXT: #define __INT64_C_SUFFIX__ L +// AARCH64-NEXT: #define __INT64_FMTd__ "ld" +// AARCH64-NEXT: #define __INT64_FMTi__ "li" +// AARCH64-NEXT: #define __INT64_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __INT64_TYPE__ long int +// AARCH64-NEXT: #define __INT8_C_SUFFIX__ +// AARCH64-NEXT: #define __INT8_FMTd__ "hhd" +// AARCH64-NEXT: #define __INT8_FMTi__ "hhi" +// AARCH64-NEXT: #define __INT8_MAX__ 127 +// AARCH64-NEXT: #define __INT8_TYPE__ signed char +// AARCH64-NEXT: #define __INTMAX_C_SUFFIX__ L +// AARCH64-NEXT: #define __INTMAX_FMTd__ "ld" +// AARCH64-NEXT: #define __INTMAX_FMTi__ "li" +// AARCH64-NEXT: #define __INTMAX_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __INTMAX_TYPE__ long int +// AARCH64-NEXT: #define __INTMAX_WIDTH__ 64 +// AARCH64-NEXT: #define __INTPTR_FMTd__ "ld" +// AARCH64-NEXT: #define __INTPTR_FMTi__ "li" +// AARCH64-NEXT: #define __INTPTR_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __INTPTR_TYPE__ long int +// AARCH64-NEXT: #define __INTPTR_WIDTH__ 64 +// AARCH64-NEXT: #define __INT_FAST16_FMTd__ "hd" +// AARCH64-NEXT: #define __INT_FAST16_FMTi__ "hi" +// AARCH64-NEXT: #define __INT_FAST16_MAX__ 32767 +// AARCH64-NEXT: #define __INT_FAST16_TYPE__ short +// AARCH64-NEXT: #define __INT_FAST32_FMTd__ "d" +// AARCH64-NEXT: #define __INT_FAST32_FMTi__ "i" +// AARCH64-NEXT: #define __INT_FAST32_MAX__ 2147483647 +// AARCH64-NEXT: #define __INT_FAST32_TYPE__ int +// AARCH64-NEXT: #define __INT_FAST64_FMTd__ "ld" +// AARCH64-NEXT: #define __INT_FAST64_FMTi__ "li" +// AARCH64-NEXT: #define __INT_FAST64_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __INT_FAST64_TYPE__ long int +// AARCH64-NEXT: #define __INT_FAST8_FMTd__ "hhd" +// AARCH64-NEXT: #define __INT_FAST8_FMTi__ "hhi" +// AARCH64-NEXT: #define __INT_FAST8_MAX__ 127 +// AARCH64-NEXT: #define __INT_FAST8_TYPE__ signed char +// AARCH64-NEXT: #define __INT_LEAST16_FMTd__ "hd" +// AARCH64-NEXT: #define __INT_LEAST16_FMTi__ "hi" +// AARCH64-NEXT: #define __INT_LEAST16_MAX__ 32767 +// AARCH64-NEXT: #define __INT_LEAST16_TYPE__ short +// AARCH64-NEXT: #define __INT_LEAST32_FMTd__ "d" +// AARCH64-NEXT: #define __INT_LEAST32_FMTi__ "i" +// AARCH64-NEXT: #define __INT_LEAST32_MAX__ 2147483647 +// AARCH64-NEXT: #define __INT_LEAST32_TYPE__ int +// AARCH64-NEXT: #define __INT_LEAST64_FMTd__ "ld" +// AARCH64-NEXT: #define __INT_LEAST64_FMTi__ "li" +// AARCH64-NEXT: #define __INT_LEAST64_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __INT_LEAST64_TYPE__ long int +// AARCH64-NEXT: #define __INT_LEAST8_FMTd__ "hhd" +// AARCH64-NEXT: #define __INT_LEAST8_FMTi__ "hhi" +// AARCH64-NEXT: #define __INT_LEAST8_MAX__ 127 +// AARCH64-NEXT: #define __INT_LEAST8_TYPE__ signed char +// AARCH64-NEXT: #define __INT_MAX__ 2147483647 +// AARCH64-NEXT: #define __LDBL_DECIMAL_DIG__ 36 +// AARCH64-NEXT: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L +// AARCH64-NEXT: #define __LDBL_DIG__ 33 +// AARCH64-NEXT: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L +// AARCH64-NEXT: #define __LDBL_HAS_DENORM__ 1 +// AARCH64-NEXT: #define __LDBL_HAS_INFINITY__ 1 +// AARCH64-NEXT: #define __LDBL_HAS_QUIET_NAN__ 1 +// AARCH64-NEXT: #define __LDBL_MANT_DIG__ 113 +// AARCH64-NEXT: #define __LDBL_MAX_10_EXP__ 4932 +// AARCH64-NEXT: #define __LDBL_MAX_EXP__ 16384 +// AARCH64-NEXT: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L +// AARCH64-NEXT: #define __LDBL_MIN_10_EXP__ (-4931) +// AARCH64-NEXT: #define __LDBL_MIN_EXP__ (-16381) +// AARCH64-NEXT: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L +// AARCH64_LE-NEXT: #define __LITTLE_ENDIAN__ 1 +// AARCH64-NEXT: #define __LONG_LONG_MAX__ 9223372036854775807LL +// AARCH64-NEXT: #define __LONG_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __LP64__ 1 +// AARCH64-NEXT: #define __NO_INLINE__ 1 +// AARCH64-NEXT: #define __OBJC_BOOL_IS_BOOL 0 +// AARCH64-NEXT: #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 +// AARCH64-NEXT: #define __OPENCL_MEMORY_SCOPE_DEVICE 2 +// AARCH64-NEXT: #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 +// AARCH64-NEXT: #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 +// AARCH64-NEXT: #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 +// AARCH64-NEXT: #define __ORDER_BIG_ENDIAN__ 4321 +// AARCH64-NEXT: #define __ORDER_LITTLE_ENDIAN__ 1234 +// AARCH64-NEXT: #define __ORDER_PDP_ENDIAN__ 3412 +// AARCH64-NEXT: #define __POINTER_WIDTH__ 64 +// AARCH64-NEXT: #define __PRAGMA_REDEFINE_EXTNAME 1 +// AARCH64-NEXT: #define __PTRDIFF_FMTd__ "ld" +// AARCH64-NEXT: #define __PTRDIFF_FMTi__ "li" +// AARCH64-NEXT: #define __PTRDIFF_MAX__ 9223372036854775807L +// AARCH64-NEXT: #define __PTRDIFF_TYPE__ long int +// AARCH64-NEXT: #define __PTRDIFF_WIDTH__ 64 +// AARCH64-NEXT: #define __SCHAR_MAX__ 127 +// AARCH64-NEXT: #define __SHRT_MAX__ 32767 +// AARCH64-NEXT: #define __SIG_ATOMIC_MAX__ 2147483647 +// AARCH64-NEXT: #define __SIG_ATOMIC_WIDTH__ 32 +// AARCH64-NEXT: #define __SIZEOF_DOUBLE__ 8 +// AARCH64-NEXT: #define __SIZEOF_FLOAT__ 4 +// AARCH64-NEXT: #define __SIZEOF_INT128__ 16 +// AARCH64-NEXT: #define __SIZEOF_INT__ 4 +// AARCH64-NEXT: #define __SIZEOF_LONG_DOUBLE__ 16 +// AARCH64-NEXT: #define __SIZEOF_LONG_LONG__ 8 +// AARCH64-NEXT: #define __SIZEOF_LONG__ 8 +// AARCH64-NEXT: #define __SIZEOF_POINTER__ 8 +// AARCH64-NEXT: #define __SIZEOF_PTRDIFF_T__ 8 +// AARCH64-NEXT: #define __SIZEOF_SHORT__ 2 +// AARCH64-NEXT: #define __SIZEOF_SIZE_T__ 8 +// AARCH64-NEXT: #define __SIZEOF_WCHAR_T__ 4 +// AARCH64-NEXT: #define __SIZEOF_WINT_T__ 4 +// AARCH64-NEXT: #define __SIZE_FMTX__ "lX" +// AARCH64-NEXT: #define __SIZE_FMTo__ "lo" +// AARCH64-NEXT: #define __SIZE_FMTu__ "lu" +// AARCH64-NEXT: #define __SIZE_FMTx__ "lx" +// AARCH64-NEXT: #define __SIZE_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __SIZE_TYPE__ long unsigned int +// AARCH64-NEXT: #define __SIZE_WIDTH__ 64 +// AARCH64_CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// AARCH64-NEXT: #define __STDC_HOSTED__ 1 +// AARCH64-NEXT: #define __STDC_UTF_16__ 1 +// AARCH64-NEXT: #define __STDC_UTF_32__ 1 +// AARCH64_C: #define __STDC_VERSION__ 201112L +// AARCH64-NEXT: #define __STDC__ 1 +// AARCH64-NEXT: #define __UINT16_C_SUFFIX__ +// AARCH64-NEXT: #define __UINT16_FMTX__ "hX" +// AARCH64-NEXT: #define __UINT16_FMTo__ "ho" +// AARCH64-NEXT: #define __UINT16_FMTu__ "hu" +// AARCH64-NEXT: #define __UINT16_FMTx__ "hx" +// AARCH64-NEXT: #define __UINT16_MAX__ 65535 +// AARCH64-NEXT: #define __UINT16_TYPE__ unsigned short +// AARCH64-NEXT: #define __UINT32_C_SUFFIX__ U +// AARCH64-NEXT: #define __UINT32_FMTX__ "X" +// AARCH64-NEXT: #define __UINT32_FMTo__ "o" +// AARCH64-NEXT: #define __UINT32_FMTu__ "u" +// AARCH64-NEXT: #define __UINT32_FMTx__ "x" +// AARCH64-NEXT: #define __UINT32_MAX__ 4294967295U +// AARCH64-NEXT: #define __UINT32_TYPE__ unsigned int +// AARCH64-NEXT: #define __UINT64_C_SUFFIX__ UL +// AARCH64-NEXT: #define __UINT64_FMTX__ "lX" +// AARCH64-NEXT: #define __UINT64_FMTo__ "lo" +// AARCH64-NEXT: #define __UINT64_FMTu__ "lu" +// AARCH64-NEXT: #define __UINT64_FMTx__ "lx" +// AARCH64-NEXT: #define __UINT64_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __UINT64_TYPE__ long unsigned int +// AARCH64-NEXT: #define __UINT8_C_SUFFIX__ +// AARCH64-NEXT: #define __UINT8_FMTX__ "hhX" +// AARCH64-NEXT: #define __UINT8_FMTo__ "hho" +// AARCH64-NEXT: #define __UINT8_FMTu__ "hhu" +// AARCH64-NEXT: #define __UINT8_FMTx__ "hhx" +// AARCH64-NEXT: #define __UINT8_MAX__ 255 +// AARCH64-NEXT: #define __UINT8_TYPE__ unsigned char +// AARCH64-NEXT: #define __UINTMAX_C_SUFFIX__ UL +// AARCH64-NEXT: #define __UINTMAX_FMTX__ "lX" +// AARCH64-NEXT: #define __UINTMAX_FMTo__ "lo" +// AARCH64-NEXT: #define __UINTMAX_FMTu__ "lu" +// AARCH64-NEXT: #define __UINTMAX_FMTx__ "lx" +// AARCH64-NEXT: #define __UINTMAX_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __UINTMAX_TYPE__ long unsigned int +// AARCH64-NEXT: #define __UINTMAX_WIDTH__ 64 +// AARCH64-NEXT: #define __UINTPTR_FMTX__ "lX" +// AARCH64-NEXT: #define __UINTPTR_FMTo__ "lo" +// AARCH64-NEXT: #define __UINTPTR_FMTu__ "lu" +// AARCH64-NEXT: #define __UINTPTR_FMTx__ "lx" +// AARCH64-NEXT: #define __UINTPTR_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __UINTPTR_TYPE__ long unsigned int +// AARCH64-NEXT: #define __UINTPTR_WIDTH__ 64 +// AARCH64-NEXT: #define __UINT_FAST16_FMTX__ "hX" +// AARCH64-NEXT: #define __UINT_FAST16_FMTo__ "ho" +// AARCH64-NEXT: #define __UINT_FAST16_FMTu__ "hu" +// AARCH64-NEXT: #define __UINT_FAST16_FMTx__ "hx" +// AARCH64-NEXT: #define __UINT_FAST16_MAX__ 65535 +// AARCH64-NEXT: #define __UINT_FAST16_TYPE__ unsigned short +// AARCH64-NEXT: #define __UINT_FAST32_FMTX__ "X" +// AARCH64-NEXT: #define __UINT_FAST32_FMTo__ "o" +// AARCH64-NEXT: #define __UINT_FAST32_FMTu__ "u" +// AARCH64-NEXT: #define __UINT_FAST32_FMTx__ "x" +// AARCH64-NEXT: #define __UINT_FAST32_MAX__ 4294967295U +// AARCH64-NEXT: #define __UINT_FAST32_TYPE__ unsigned int +// AARCH64-NEXT: #define __UINT_FAST64_FMTX__ "lX" +// AARCH64-NEXT: #define __UINT_FAST64_FMTo__ "lo" +// AARCH64-NEXT: #define __UINT_FAST64_FMTu__ "lu" +// AARCH64-NEXT: #define __UINT_FAST64_FMTx__ "lx" +// AARCH64-NEXT: #define __UINT_FAST64_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __UINT_FAST64_TYPE__ long unsigned int +// AARCH64-NEXT: #define __UINT_FAST8_FMTX__ "hhX" +// AARCH64-NEXT: #define __UINT_FAST8_FMTo__ "hho" +// AARCH64-NEXT: #define __UINT_FAST8_FMTu__ "hhu" +// AARCH64-NEXT: #define __UINT_FAST8_FMTx__ "hhx" +// AARCH64-NEXT: #define __UINT_FAST8_MAX__ 255 +// AARCH64-NEXT: #define __UINT_FAST8_TYPE__ unsigned char +// AARCH64-NEXT: #define __UINT_LEAST16_FMTX__ "hX" +// AARCH64-NEXT: #define __UINT_LEAST16_FMTo__ "ho" +// AARCH64-NEXT: #define __UINT_LEAST16_FMTu__ "hu" +// AARCH64-NEXT: #define __UINT_LEAST16_FMTx__ "hx" +// AARCH64-NEXT: #define __UINT_LEAST16_MAX__ 65535 +// AARCH64-NEXT: #define __UINT_LEAST16_TYPE__ unsigned short +// AARCH64-NEXT: #define __UINT_LEAST32_FMTX__ "X" +// AARCH64-NEXT: #define __UINT_LEAST32_FMTo__ "o" +// AARCH64-NEXT: #define __UINT_LEAST32_FMTu__ "u" +// AARCH64-NEXT: #define __UINT_LEAST32_FMTx__ "x" +// AARCH64-NEXT: #define __UINT_LEAST32_MAX__ 4294967295U +// AARCH64-NEXT: #define __UINT_LEAST32_TYPE__ unsigned int +// AARCH64-NEXT: #define __UINT_LEAST64_FMTX__ "lX" +// AARCH64-NEXT: #define __UINT_LEAST64_FMTo__ "lo" +// AARCH64-NEXT: #define __UINT_LEAST64_FMTu__ "lu" +// AARCH64-NEXT: #define __UINT_LEAST64_FMTx__ "lx" +// AARCH64-NEXT: #define __UINT_LEAST64_MAX__ 18446744073709551615UL +// AARCH64-NEXT: #define __UINT_LEAST64_TYPE__ long unsigned int +// AARCH64-NEXT: #define __UINT_LEAST8_FMTX__ "hhX" +// AARCH64-NEXT: #define __UINT_LEAST8_FMTo__ "hho" +// AARCH64-NEXT: #define __UINT_LEAST8_FMTu__ "hhu" +// AARCH64-NEXT: #define __UINT_LEAST8_FMTx__ "hhx" +// AARCH64-NEXT: #define __UINT_LEAST8_MAX__ 255 +// AARCH64-NEXT: #define __UINT_LEAST8_TYPE__ unsigned char +// AARCH64-NEXT: #define __USER_LABEL_PREFIX__ +// AARCH64-NEXT: #define __VERSION__ "{{.*}}" +// AARCH64-NEXT: #define __WCHAR_MAX__ 4294967295U +// AARCH64-NEXT: #define __WCHAR_TYPE__ unsigned int +// AARCH64-NEXT: #define __WCHAR_UNSIGNED__ 1 +// AARCH64-NEXT: #define __WCHAR_WIDTH__ 32 +// AARCH64-NEXT: #define __WINT_MAX__ 2147483647 +// AARCH64-NEXT: #define __WINT_TYPE__ int +// AARCH64-NEXT: #define __WINT_WIDTH__ 32 +// AARCH64-NEXT: #define __aarch64__ 1 + +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-apple-ios7.0 < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-DARWIN %s + +// AARCH64-DARWIN: #define _LP64 1 +// AARCH64-DARWIN-NOT: #define __AARCH64EB__ 1 +// AARCH64-DARWIN: #define __AARCH64EL__ 1 +// AARCH64-DARWIN-NOT: #define __AARCH_BIG_ENDIAN 1 +// AARCH64-DARWIN: #define __ARM_64BIT_STATE 1 +// AARCH64-DARWIN: #define __ARM_ARCH 8 +// AARCH64-DARWIN: #define __ARM_ARCH_ISA_A64 1 +// AARCH64-DARWIN-NOT: #define __ARM_BIG_ENDIAN 1 +// AARCH64-DARWIN: #define __BIGGEST_ALIGNMENT__ 8 +// AARCH64-DARWIN: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +// AARCH64-DARWIN: #define __CHAR16_TYPE__ unsigned short +// AARCH64-DARWIN: #define __CHAR32_TYPE__ unsigned int +// AARCH64-DARWIN: #define __CHAR_BIT__ 8 +// AARCH64-DARWIN: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +// AARCH64-DARWIN: #define __DBL_DIG__ 15 +// AARCH64-DARWIN: #define __DBL_EPSILON__ 2.2204460492503131e-16 +// AARCH64-DARWIN: #define __DBL_HAS_DENORM__ 1 +// AARCH64-DARWIN: #define __DBL_HAS_INFINITY__ 1 +// AARCH64-DARWIN: #define __DBL_HAS_QUIET_NAN__ 1 +// AARCH64-DARWIN: #define __DBL_MANT_DIG__ 53 +// AARCH64-DARWIN: #define __DBL_MAX_10_EXP__ 308 +// AARCH64-DARWIN: #define __DBL_MAX_EXP__ 1024 +// AARCH64-DARWIN: #define __DBL_MAX__ 1.7976931348623157e+308 +// AARCH64-DARWIN: #define __DBL_MIN_10_EXP__ (-307) +// AARCH64-DARWIN: #define __DBL_MIN_EXP__ (-1021) +// AARCH64-DARWIN: #define __DBL_MIN__ 2.2250738585072014e-308 +// AARCH64-DARWIN: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ +// AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F +// AARCH64-DARWIN: #define __FLT_DIG__ 6 +// AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F +// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1 +// AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1 +// AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1 +// AARCH64-DARWIN: #define __FLT_MANT_DIG__ 24 +// AARCH64-DARWIN: #define __FLT_MAX_10_EXP__ 38 +// AARCH64-DARWIN: #define __FLT_MAX_EXP__ 128 +// AARCH64-DARWIN: #define __FLT_MAX__ 3.40282347e+38F +// AARCH64-DARWIN: #define __FLT_MIN_10_EXP__ (-37) +// AARCH64-DARWIN: #define __FLT_MIN_EXP__ (-125) +// AARCH64-DARWIN: #define __FLT_MIN__ 1.17549435e-38F +// AARCH64-DARWIN: #define __FLT_RADIX__ 2 +// AARCH64-DARWIN: #define __INT16_C_SUFFIX__ +// AARCH64-DARWIN: #define __INT16_FMTd__ "hd" +// AARCH64-DARWIN: #define __INT16_FMTi__ "hi" +// AARCH64-DARWIN: #define __INT16_MAX__ 32767 +// AARCH64-DARWIN: #define __INT16_TYPE__ short +// AARCH64-DARWIN: #define __INT32_C_SUFFIX__ +// AARCH64-DARWIN: #define __INT32_FMTd__ "d" +// AARCH64-DARWIN: #define __INT32_FMTi__ "i" +// AARCH64-DARWIN: #define __INT32_MAX__ 2147483647 +// AARCH64-DARWIN: #define __INT32_TYPE__ int +// AARCH64-DARWIN: #define __INT64_C_SUFFIX__ LL +// AARCH64-DARWIN: #define __INT64_FMTd__ "lld" +// AARCH64-DARWIN: #define __INT64_FMTi__ "lli" +// AARCH64-DARWIN: #define __INT64_MAX__ 9223372036854775807LL +// AARCH64-DARWIN: #define __INT64_TYPE__ long long int +// AARCH64-DARWIN: #define __INT8_C_SUFFIX__ +// AARCH64-DARWIN: #define __INT8_FMTd__ "hhd" +// AARCH64-DARWIN: #define __INT8_FMTi__ "hhi" +// AARCH64-DARWIN: #define __INT8_MAX__ 127 +// AARCH64-DARWIN: #define __INT8_TYPE__ signed char +// AARCH64-DARWIN: #define __INTMAX_C_SUFFIX__ L +// AARCH64-DARWIN: #define __INTMAX_FMTd__ "ld" +// AARCH64-DARWIN: #define __INTMAX_FMTi__ "li" +// AARCH64-DARWIN: #define __INTMAX_MAX__ 9223372036854775807L +// AARCH64-DARWIN: #define __INTMAX_TYPE__ long int +// AARCH64-DARWIN: #define __INTMAX_WIDTH__ 64 +// AARCH64-DARWIN: #define __INTPTR_FMTd__ "ld" +// AARCH64-DARWIN: #define __INTPTR_FMTi__ "li" +// AARCH64-DARWIN: #define __INTPTR_MAX__ 9223372036854775807L +// AARCH64-DARWIN: #define __INTPTR_TYPE__ long int +// AARCH64-DARWIN: #define __INTPTR_WIDTH__ 64 +// AARCH64-DARWIN: #define __INT_FAST16_FMTd__ "hd" +// AARCH64-DARWIN: #define __INT_FAST16_FMTi__ "hi" +// AARCH64-DARWIN: #define __INT_FAST16_MAX__ 32767 +// AARCH64-DARWIN: #define __INT_FAST16_TYPE__ short +// AARCH64-DARWIN: #define __INT_FAST32_FMTd__ "d" +// AARCH64-DARWIN: #define __INT_FAST32_FMTi__ "i" +// AARCH64-DARWIN: #define __INT_FAST32_MAX__ 2147483647 +// AARCH64-DARWIN: #define __INT_FAST32_TYPE__ int +// AARCH64-DARWIN: #define __INT_FAST64_FMTd__ "lld" +// AARCH64-DARWIN: #define __INT_FAST64_FMTi__ "lli" +// AARCH64-DARWIN: #define __INT_FAST64_MAX__ 9223372036854775807LL +// AARCH64-DARWIN: #define __INT_FAST64_TYPE__ long long int +// AARCH64-DARWIN: #define __INT_FAST8_FMTd__ "hhd" +// AARCH64-DARWIN: #define __INT_FAST8_FMTi__ "hhi" +// AARCH64-DARWIN: #define __INT_FAST8_MAX__ 127 +// AARCH64-DARWIN: #define __INT_FAST8_TYPE__ signed char +// AARCH64-DARWIN: #define __INT_LEAST16_FMTd__ "hd" +// AARCH64-DARWIN: #define __INT_LEAST16_FMTi__ "hi" +// AARCH64-DARWIN: #define __INT_LEAST16_MAX__ 32767 +// AARCH64-DARWIN: #define __INT_LEAST16_TYPE__ short +// AARCH64-DARWIN: #define __INT_LEAST32_FMTd__ "d" +// AARCH64-DARWIN: #define __INT_LEAST32_FMTi__ "i" +// AARCH64-DARWIN: #define __INT_LEAST32_MAX__ 2147483647 +// AARCH64-DARWIN: #define __INT_LEAST32_TYPE__ int +// AARCH64-DARWIN: #define __INT_LEAST64_FMTd__ "lld" +// AARCH64-DARWIN: #define __INT_LEAST64_FMTi__ "lli" +// AARCH64-DARWIN: #define __INT_LEAST64_MAX__ 9223372036854775807LL +// AARCH64-DARWIN: #define __INT_LEAST64_TYPE__ long long int +// AARCH64-DARWIN: #define __INT_LEAST8_FMTd__ "hhd" +// AARCH64-DARWIN: #define __INT_LEAST8_FMTi__ "hhi" +// AARCH64-DARWIN: #define __INT_LEAST8_MAX__ 127 +// AARCH64-DARWIN: #define __INT_LEAST8_TYPE__ signed char +// AARCH64-DARWIN: #define __INT_MAX__ 2147483647 +// AARCH64-DARWIN: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L +// AARCH64-DARWIN: #define __LDBL_DIG__ 15 +// AARCH64-DARWIN: #define __LDBL_EPSILON__ 2.2204460492503131e-16L +// AARCH64-DARWIN: #define __LDBL_HAS_DENORM__ 1 +// AARCH64-DARWIN: #define __LDBL_HAS_INFINITY__ 1 +// AARCH64-DARWIN: #define __LDBL_HAS_QUIET_NAN__ 1 +// AARCH64-DARWIN: #define __LDBL_MANT_DIG__ 53 +// AARCH64-DARWIN: #define __LDBL_MAX_10_EXP__ 308 +// AARCH64-DARWIN: #define __LDBL_MAX_EXP__ 1024 +// AARCH64-DARWIN: #define __LDBL_MAX__ 1.7976931348623157e+308L +// AARCH64-DARWIN: #define __LDBL_MIN_10_EXP__ (-307) +// AARCH64-DARWIN: #define __LDBL_MIN_EXP__ (-1021) +// AARCH64-DARWIN: #define __LDBL_MIN__ 2.2250738585072014e-308L +// AARCH64-DARWIN: #define __LONG_LONG_MAX__ 9223372036854775807LL +// AARCH64-DARWIN: #define __LONG_MAX__ 9223372036854775807L +// AARCH64-DARWIN: #define __LP64__ 1 +// AARCH64-DARWIN: #define __POINTER_WIDTH__ 64 +// AARCH64-DARWIN: #define __PTRDIFF_TYPE__ long int +// AARCH64-DARWIN: #define __PTRDIFF_WIDTH__ 64 +// AARCH64-DARWIN: #define __SCHAR_MAX__ 127 +// AARCH64-DARWIN: #define __SHRT_MAX__ 32767 +// AARCH64-DARWIN: #define __SIG_ATOMIC_MAX__ 2147483647 +// AARCH64-DARWIN: #define __SIG_ATOMIC_WIDTH__ 32 +// AARCH64-DARWIN: #define __SIZEOF_DOUBLE__ 8 +// AARCH64-DARWIN: #define __SIZEOF_FLOAT__ 4 +// AARCH64-DARWIN: #define __SIZEOF_INT128__ 16 +// AARCH64-DARWIN: #define __SIZEOF_INT__ 4 +// AARCH64-DARWIN: #define __SIZEOF_LONG_DOUBLE__ 8 +// AARCH64-DARWIN: #define __SIZEOF_LONG_LONG__ 8 +// AARCH64-DARWIN: #define __SIZEOF_LONG__ 8 +// AARCH64-DARWIN: #define __SIZEOF_POINTER__ 8 +// AARCH64-DARWIN: #define __SIZEOF_PTRDIFF_T__ 8 +// AARCH64-DARWIN: #define __SIZEOF_SHORT__ 2 +// AARCH64-DARWIN: #define __SIZEOF_SIZE_T__ 8 +// AARCH64-DARWIN: #define __SIZEOF_WCHAR_T__ 4 +// AARCH64-DARWIN: #define __SIZEOF_WINT_T__ 4 +// AARCH64-DARWIN: #define __SIZE_MAX__ 18446744073709551615UL +// AARCH64-DARWIN: #define __SIZE_TYPE__ long unsigned int +// AARCH64-DARWIN: #define __SIZE_WIDTH__ 64 +// AARCH64-DARWIN: #define __UINT16_C_SUFFIX__ +// AARCH64-DARWIN: #define __UINT16_MAX__ 65535 +// AARCH64-DARWIN: #define __UINT16_TYPE__ unsigned short +// AARCH64-DARWIN: #define __UINT32_C_SUFFIX__ U +// AARCH64-DARWIN: #define __UINT32_MAX__ 4294967295U +// AARCH64-DARWIN: #define __UINT32_TYPE__ unsigned int +// AARCH64-DARWIN: #define __UINT64_C_SUFFIX__ ULL +// AARCH64-DARWIN: #define __UINT64_MAX__ 18446744073709551615ULL +// AARCH64-DARWIN: #define __UINT64_TYPE__ long long unsigned int +// AARCH64-DARWIN: #define __UINT8_C_SUFFIX__ +// AARCH64-DARWIN: #define __UINT8_MAX__ 255 +// AARCH64-DARWIN: #define __UINT8_TYPE__ unsigned char +// AARCH64-DARWIN: #define __UINTMAX_C_SUFFIX__ UL +// AARCH64-DARWIN: #define __UINTMAX_MAX__ 18446744073709551615UL +// AARCH64-DARWIN: #define __UINTMAX_TYPE__ long unsigned int +// AARCH64-DARWIN: #define __UINTMAX_WIDTH__ 64 +// AARCH64-DARWIN: #define __UINTPTR_MAX__ 18446744073709551615UL +// AARCH64-DARWIN: #define __UINTPTR_TYPE__ long unsigned int +// AARCH64-DARWIN: #define __UINTPTR_WIDTH__ 64 +// AARCH64-DARWIN: #define __UINT_FAST16_MAX__ 65535 +// AARCH64-DARWIN: #define __UINT_FAST16_TYPE__ unsigned short +// AARCH64-DARWIN: #define __UINT_FAST32_MAX__ 4294967295U +// AARCH64-DARWIN: #define __UINT_FAST32_TYPE__ unsigned int +// AARCH64-DARWIN: #define __UINT_FAST64_MAX__ 18446744073709551615ULL +// AARCH64-DARWIN: #define __UINT_FAST64_TYPE__ long long unsigned int +// AARCH64-DARWIN: #define __UINT_FAST8_MAX__ 255 +// AARCH64-DARWIN: #define __UINT_FAST8_TYPE__ unsigned char +// AARCH64-DARWIN: #define __UINT_LEAST16_MAX__ 65535 +// AARCH64-DARWIN: #define __UINT_LEAST16_TYPE__ unsigned short +// AARCH64-DARWIN: #define __UINT_LEAST32_MAX__ 4294967295U +// AARCH64-DARWIN: #define __UINT_LEAST32_TYPE__ unsigned int +// AARCH64-DARWIN: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL +// AARCH64-DARWIN: #define __UINT_LEAST64_TYPE__ long long unsigned int +// AARCH64-DARWIN: #define __UINT_LEAST8_MAX__ 255 +// AARCH64-DARWIN: #define __UINT_LEAST8_TYPE__ unsigned char +// AARCH64-DARWIN: #define __USER_LABEL_PREFIX__ _ +// AARCH64-DARWIN: #define __WCHAR_MAX__ 2147483647 +// AARCH64-DARWIN: #define __WCHAR_TYPE__ int +// AARCH64-DARWIN-NOT: #define __WCHAR_UNSIGNED__ +// AARCH64-DARWIN: #define __WCHAR_WIDTH__ 32 +// AARCH64-DARWIN: #define __WINT_TYPE__ int +// AARCH64-DARWIN: #define __WINT_WIDTH__ 32 +// AARCH64-DARWIN: #define __aarch64__ 1 + +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-windows-msvc < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-MSVC %s + +// AARCH64-MSVC: #define _INTEGRAL_MAX_BITS 64 +// AARCH64-MSVC-NOT: #define _LP64 1 +// AARCH64-MSVC: #define _M_ARM64 1 +// AARCH64-MSVC: #define _WIN32 1 +// AARCH64-MSVC: #define _WIN64 1 +// AARCH64-MSVC: #define __AARCH64EL__ 1 +// AARCH64-MSVC: #define __ARM_64BIT_STATE 1 +// AARCH64-MSVC: #define __ARM_ACLE 200 +// AARCH64-MSVC: #define __ARM_ALIGN_MAX_STACK_PWR 4 +// AARCH64-MSVC: #define __ARM_ARCH 8 +// AARCH64-MSVC: #define __ARM_ARCH_ISA_A64 1 +// AARCH64-MSVC: #define __ARM_ARCH_PROFILE 'A' +// AARCH64-MSVC: #define __ARM_FEATURE_CLZ 1 +// AARCH64-MSVC: #define __ARM_FEATURE_DIRECTED_ROUNDING 1 +// AARCH64-MSVC: #define __ARM_FEATURE_DIV 1 +// AARCH64-MSVC: #define __ARM_FEATURE_FMA 1 +// AARCH64-MSVC: #define __ARM_FEATURE_IDIV 1 +// AARCH64-MSVC: #define __ARM_FEATURE_LDREX 0xF +// AARCH64-MSVC: #define __ARM_FEATURE_NUMERIC_MAXMIN 1 +// AARCH64-MSVC: #define __ARM_FEATURE_UNALIGNED 1 +// AARCH64-MSVC: #define __ARM_FP 0xE +// AARCH64-MSVC: #define __ARM_FP16_ARGS 1 +// AARCH64-MSVC: #define __ARM_FP16_FORMAT_IEEE 1 +// AARCH64-MSVC: #define __ARM_PCS_AAPCS64 1 +// AARCH64-MSVC: #define __ARM_SIZEOF_MINIMAL_ENUM 4 +// AARCH64-MSVC: #define __ARM_SIZEOF_WCHAR_T 4 +// AARCH64-MSVC: #define __BIGGEST_ALIGNMENT__ 16 +// AARCH64-MSVC: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +// AARCH64-MSVC: #define __CHAR16_TYPE__ unsigned short +// AARCH64-MSVC: #define __CHAR32_TYPE__ unsigned int +// AARCH64-MSVC: #define __CHAR_BIT__ 8 +// AARCH64-MSVC: #define __CONSTANT_CFSTRINGS__ 1 +// AARCH64-MSVC: #define __DBL_DECIMAL_DIG__ 17 +// AARCH64-MSVC: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +// AARCH64-MSVC: #define __DBL_DIG__ 15 +// AARCH64-MSVC: #define __DBL_EPSILON__ 2.2204460492503131e-16 +// AARCH64-MSVC: #define __DBL_HAS_DENORM__ 1 +// AARCH64-MSVC: #define __DBL_HAS_INFINITY__ 1 +// AARCH64-MSVC: #define __DBL_HAS_QUIET_NAN__ 1 +// AARCH64-MSVC: #define __DBL_MANT_DIG__ 53 +// AARCH64-MSVC: #define __DBL_MAX_10_EXP__ 308 +// AARCH64-MSVC: #define __DBL_MAX_EXP__ 1024 +// AARCH64-MSVC: #define __DBL_MAX__ 1.7976931348623157e+308 +// AARCH64-MSVC: #define __DBL_MIN_10_EXP__ (-307) +// AARCH64-MSVC: #define __DBL_MIN_EXP__ (-1021) +// AARCH64-MSVC: #define __DBL_MIN__ 2.2250738585072014e-308 +// AARCH64-MSVC: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ +// AARCH64-MSVC: #define __FINITE_MATH_ONLY__ 0 +// AARCH64-MSVC: #define __FLT_DECIMAL_DIG__ 9 +// AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F +// AARCH64-MSVC: #define __FLT_DIG__ 6 +// AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F +// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1 +// AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1 +// AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1 +// AARCH64-MSVC: #define __FLT_MANT_DIG__ 24 +// AARCH64-MSVC: #define __FLT_MAX_10_EXP__ 38 +// AARCH64-MSVC: #define __FLT_MAX_EXP__ 128 +// AARCH64-MSVC: #define __FLT_MAX__ 3.40282347e+38F +// AARCH64-MSVC: #define __FLT_MIN_10_EXP__ (-37) +// AARCH64-MSVC: #define __FLT_MIN_EXP__ (-125) +// AARCH64-MSVC: #define __FLT_MIN__ 1.17549435e-38F +// AARCH64-MSVC: #define __FLT_RADIX__ 2 +// AARCH64-MSVC: #define __INT_MAX__ 2147483647 +// AARCH64-MSVC: #define __LDBL_DECIMAL_DIG__ 17 +// AARCH64-MSVC: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L +// AARCH64-MSVC: #define __LDBL_DIG__ 15 +// AARCH64-MSVC: #define __LDBL_EPSILON__ 2.2204460492503131e-16L +// AARCH64-MSVC: #define __LDBL_HAS_DENORM__ 1 +// AARCH64-MSVC: #define __LDBL_HAS_INFINITY__ 1 +// AARCH64-MSVC: #define __LDBL_HAS_QUIET_NAN__ 1 +// AARCH64-MSVC: #define __LDBL_MANT_DIG__ 53 +// AARCH64-MSVC: #define __LDBL_MAX_10_EXP__ 308 +// AARCH64-MSVC: #define __LDBL_MAX_EXP__ 1024 +// AARCH64-MSVC: #define __LDBL_MAX__ 1.7976931348623157e+308L +// AARCH64-MSVC: #define __LDBL_MIN_10_EXP__ (-307) +// AARCH64-MSVC: #define __LDBL_MIN_EXP__ (-1021) +// AARCH64-MSVC: #define __LDBL_MIN__ 2.2250738585072014e-308L +// AARCH64-MSVC: #define __LITTLE_ENDIAN__ 1 +// AARCH64-MSVC: #define __LONG_LONG_MAX__ 9223372036854775807LL +// AARCH64-MSVC: #define __LONG_MAX__ 2147483647L +// AARCH64-MSVC-NOT: #define __LP64__ 1 +// AARCH64-MSVC: #define __NO_INLINE__ 1 +// AARCH64-MSVC: #define __OBJC_BOOL_IS_BOOL 0 +// AARCH64-MSVC: #define __ORDER_BIG_ENDIAN__ 4321 +// AARCH64-MSVC: #define __ORDER_LITTLE_ENDIAN__ 1234 +// AARCH64-MSVC: #define __ORDER_PDP_ENDIAN__ 3412 +// AARCH64-MSVC: #define __POINTER_WIDTH__ 64 +// AARCH64-MSVC: #define __PRAGMA_REDEFINE_EXTNAME 1 +// AARCH64-MSVC: #define __SCHAR_MAX__ 127 +// AARCH64-MSVC: #define __SHRT_MAX__ 32767 +// AARCH64-MSVC: #define __SIG_ATOMIC_MAX__ 2147483647 +// AARCH64-MSVC: #define __SIG_ATOMIC_WIDTH__ 32 +// AARCH64-MSVC: #define __SIZEOF_DOUBLE__ 8 +// AARCH64-MSVC: #define __SIZEOF_FLOAT__ 4 +// AARCH64-MSVC: #define __SIZEOF_INT128__ 16 +// AARCH64-MSVC: #define __SIZEOF_INT__ 4 +// AARCH64-MSVC: #define __SIZEOF_LONG_DOUBLE__ 8 +// AARCH64-MSVC: #define __SIZEOF_LONG_LONG__ 8 +// AARCH64-MSVC: #define __SIZEOF_LONG__ 4 +// AARCH64-MSVC: #define __SIZEOF_POINTER__ 8 +// AARCH64-MSVC: #define __SIZEOF_PTRDIFF_T__ 8 +// AARCH64-MSVC: #define __SIZEOF_SHORT__ 2 +// AARCH64-MSVC: #define __SIZEOF_SIZE_T__ 8 +// AARCH64-MSVC: #define __SIZEOF_WCHAR_T__ 2 +// AARCH64-MSVC: #define __SIZEOF_WINT_T__ 2 +// AARCH64-MSVC: #define __SIZE_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __SIZE_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __SIZE_WIDTH__ 64 +// AARCH64-MSVC: #define __STDC_HOSTED__ 0 +// AARCH64-MSVC: #define __STDC_UTF_16__ 1 +// AARCH64-MSVC: #define __STDC_UTF_32__ 1 +// AARCH64-MSVC: #define __STDC_VERSION__ 201112L +// AARCH64-MSVC: #define __STDC__ 1 +// AARCH64-MSVC: #define __UINT16_C_SUFFIX__ +// AARCH64-MSVC: #define __UINT16_MAX__ 65535 +// AARCH64-MSVC: #define __UINT16_TYPE__ unsigned short +// AARCH64-MSVC: #define __UINT32_C_SUFFIX__ U +// AARCH64-MSVC: #define __UINT32_MAX__ 4294967295U +// AARCH64-MSVC: #define __UINT32_TYPE__ unsigned int +// AARCH64-MSVC: #define __UINT64_C_SUFFIX__ ULL +// AARCH64-MSVC: #define __UINT64_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __UINT64_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __UINT8_C_SUFFIX__ +// AARCH64-MSVC: #define __UINT8_MAX__ 255 +// AARCH64-MSVC: #define __UINT8_TYPE__ unsigned char +// AARCH64-MSVC: #define __UINTMAX_C_SUFFIX__ ULL +// AARCH64-MSVC: #define __UINTMAX_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __UINTMAX_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __UINTMAX_WIDTH__ 64 +// AARCH64-MSVC: #define __UINTPTR_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __UINTPTR_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __UINTPTR_WIDTH__ 64 +// AARCH64-MSVC: #define __UINT_FAST16_MAX__ 65535 +// AARCH64-MSVC: #define __UINT_FAST16_TYPE__ unsigned short +// AARCH64-MSVC: #define __UINT_FAST32_MAX__ 4294967295U +// AARCH64-MSVC: #define __UINT_FAST32_TYPE__ unsigned int +// AARCH64-MSVC: #define __UINT_FAST64_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __UINT_FAST64_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __UINT_FAST8_MAX__ 255 +// AARCH64-MSVC: #define __UINT_FAST8_TYPE__ unsigned char +// AARCH64-MSVC: #define __UINT_LEAST16_MAX__ 65535 +// AARCH64-MSVC: #define __UINT_LEAST16_TYPE__ unsigned short +// AARCH64-MSVC: #define __UINT_LEAST32_MAX__ 4294967295U +// AARCH64-MSVC: #define __UINT_LEAST32_TYPE__ unsigned int +// AARCH64-MSVC: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL +// AARCH64-MSVC: #define __UINT_LEAST64_TYPE__ long long unsigned int +// AARCH64-MSVC: #define __UINT_LEAST8_MAX__ 255 +// AARCH64-MSVC: #define __UINT_LEAST8_TYPE__ unsigned char +// AARCH64-MSVC: #define __USER_LABEL_PREFIX__ +// AARCH64-MSVC: #define __WCHAR_MAX__ 65535 +// AARCH64-MSVC: #define __WCHAR_TYPE__ unsigned short +// AARCH64-MSVC: #define __WCHAR_UNSIGNED__ 1 +// AARCH64-MSVC: #define __WCHAR_WIDTH__ 16 +// AARCH64-MSVC: #define __WINT_TYPE__ unsigned short +// AARCH64-MSVC: #define __WINT_WIDTH__ 16 +// AARCH64-MSVC: #define __aarch64__ 1 + +// RUN: %clang_cc1 -triple=aarch64 -E -dM -mcmodel=small -xc /dev/null | FileCheck --check-prefix=CMODEL_SMALL %s +// RUN: %clang_cc1 -triple=aarch64 -E -dM -mcmodel=tiny -xc /dev/null | FileCheck --check-prefix=CMODEL_TINY %s +// RUN: %clang_cc1 -triple=aarch64 -E -dM -mcmodel=large -xc /dev/null | FileCheck --check-prefix=CMODEL_LARGE %s + +// CMODEL_TINY: #define __AARCH64_CMODEL_TINY__ 1 +// CMODEL_SMALL: #define __AARCH64_CMODEL_SMALL__ 1 +// CMODEL_LARGE: #define __AARCH64_CMODEL_LARGE__ 1 diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 6c9508e5c634d..f38f87ddef8e6 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -9,15 +9,17 @@ // BLOCKS:#define __block __attribute__((__blocks__(byref))) // // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++20 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX2A %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++2a -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX2A %s // // CXX2A:#define __GNUG__ 4 // CXX2A:#define __GXX_EXPERIMENTAL_CXX0X__ 1 // CXX2A:#define __GXX_RTTI 1 // CXX2A:#define __GXX_WEAK__ 1 -// CXX2A:#define __cplusplus 201707L +// CXX2A:#define __cplusplus 202002L // CXX2A:#define __private_extern__ extern // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++17 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Z %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++1z -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Z %s // // CXX1Z:#define __GNUG__ 4 @@ -28,6 +30,7 @@ // CXX1Z:#define __private_extern__ extern // // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++14 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Y %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=c++1y -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Y %s // // CXX1Y:#define __GNUG__ 4 @@ -119,14 +122,16 @@ // RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s // FREESTANDING:#define __STDC_HOSTED__ 0 // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++20 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX2A %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++2a -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX2A %s // // GXX2A:#define __GNUG__ 4 // GXX2A:#define __GXX_WEAK__ 1 -// GXX2A:#define __cplusplus 201707L +// GXX2A:#define __cplusplus 202002L // GXX2A:#define __private_extern__ extern // // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++17 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Z %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++1z -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Z %s // // GXX1Z:#define __GNUG__ 4 @@ -135,6 +140,7 @@ // GXX1Z:#define __private_extern__ extern // // +// RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++14 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Y %s // RUN: %clang_cc1 -x c++ -fgnuc-version=4.2.1 -std=gnu++1y -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Y %s // // GXX1Y:#define __GNUG__ 4 @@ -271,1342 +277,12 @@ // SHORTWCHAR2: #define __WCHAR_WIDTH__ 32 // Other definitions vary from platform to platform -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s -// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 -check-prefix AARCH64-CXX %s -// -// AARCH64:#define _LP64 1 -// AARCH64-NOT:#define __AARCH64EB__ 1 -// AARCH64:#define __AARCH64EL__ 1 -// AARCH64-NOT:#define __AARCH_BIG_ENDIAN 1 -// AARCH64:#define __ARM_64BIT_STATE 1 -// AARCH64:#define __ARM_ARCH 8 -// AARCH64:#define __ARM_ARCH_ISA_A64 1 -// AARCH64-NOT:#define __ARM_BIG_ENDIAN 1 -// AARCH64:#define __BIGGEST_ALIGNMENT__ 16 -// AARCH64:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64:#define __CHAR16_TYPE__ unsigned short -// AARCH64:#define __CHAR32_TYPE__ unsigned int -// AARCH64:#define __CHAR_BIT__ 8 -// AARCH64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64:#define __DBL_DIG__ 15 -// AARCH64:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64:#define __DBL_HAS_DENORM__ 1 -// AARCH64:#define __DBL_HAS_INFINITY__ 1 -// AARCH64:#define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64:#define __DBL_MANT_DIG__ 53 -// AARCH64:#define __DBL_MAX_10_EXP__ 308 -// AARCH64:#define __DBL_MAX_EXP__ 1024 -// AARCH64:#define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64:#define __DBL_MIN_10_EXP__ (-307) -// AARCH64:#define __DBL_MIN_EXP__ (-1021) -// AARCH64:#define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64:#define __FLT16_DECIMAL_DIG__ 5 -// AARCH64:#define __FLT16_DENORM_MIN__ 5.9604644775390625e-8F16 -// AARCH64:#define __FLT16_DIG__ 3 -// AARCH64:#define __FLT16_EPSILON__ 9.765625e-4F16 -// AARCH64:#define __FLT16_HAS_DENORM__ 1 -// AARCH64:#define __FLT16_HAS_INFINITY__ 1 -// AARCH64:#define __FLT16_HAS_QUIET_NAN__ 1 -// AARCH64:#define __FLT16_MANT_DIG__ 11 -// AARCH64:#define __FLT16_MAX_10_EXP__ 4 -// AARCH64:#define __FLT16_MAX_EXP__ 16 -// AARCH64:#define __FLT16_MAX__ 6.5504e+4F16 -// AARCH64:#define __FLT16_MIN_10_EXP__ (-4) -// AARCH64:#define __FLT16_MIN_EXP__ (-13) -// AARCH64:#define __FLT16_MIN__ 6.103515625e-5F16 -// AARCH64:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64:#define __FLT_DIG__ 6 -// AARCH64:#define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64:#define __FLT_EVAL_METHOD__ 0 -// AARCH64:#define __FLT_HAS_DENORM__ 1 -// AARCH64:#define __FLT_HAS_INFINITY__ 1 -// AARCH64:#define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64:#define __FLT_MANT_DIG__ 24 -// AARCH64:#define __FLT_MAX_10_EXP__ 38 -// AARCH64:#define __FLT_MAX_EXP__ 128 -// AARCH64:#define __FLT_MAX__ 3.40282347e+38F -// AARCH64:#define __FLT_MIN_10_EXP__ (-37) -// AARCH64:#define __FLT_MIN_EXP__ (-125) -// AARCH64:#define __FLT_MIN__ 1.17549435e-38F -// AARCH64:#define __FLT_RADIX__ 2 -// AARCH64:#define __INT16_C_SUFFIX__ -// AARCH64:#define __INT16_FMTd__ "hd" -// AARCH64:#define __INT16_FMTi__ "hi" -// AARCH64:#define __INT16_MAX__ 32767 -// AARCH64:#define __INT16_TYPE__ short -// AARCH64:#define __INT32_C_SUFFIX__ -// AARCH64:#define __INT32_FMTd__ "d" -// AARCH64:#define __INT32_FMTi__ "i" -// AARCH64:#define __INT32_MAX__ 2147483647 -// AARCH64:#define __INT32_TYPE__ int -// AARCH64:#define __INT64_C_SUFFIX__ L -// AARCH64:#define __INT64_FMTd__ "ld" -// AARCH64:#define __INT64_FMTi__ "li" -// AARCH64:#define __INT64_MAX__ 9223372036854775807L -// AARCH64:#define __INT64_TYPE__ long int -// AARCH64:#define __INT8_C_SUFFIX__ -// AARCH64:#define __INT8_FMTd__ "hhd" -// AARCH64:#define __INT8_FMTi__ "hhi" -// AARCH64:#define __INT8_MAX__ 127 -// AARCH64:#define __INT8_TYPE__ signed char -// AARCH64:#define __INTMAX_C_SUFFIX__ L -// AARCH64:#define __INTMAX_FMTd__ "ld" -// AARCH64:#define __INTMAX_FMTi__ "li" -// AARCH64:#define __INTMAX_MAX__ 9223372036854775807L -// AARCH64:#define __INTMAX_TYPE__ long int -// AARCH64:#define __INTMAX_WIDTH__ 64 -// AARCH64:#define __INTPTR_FMTd__ "ld" -// AARCH64:#define __INTPTR_FMTi__ "li" -// AARCH64:#define __INTPTR_MAX__ 9223372036854775807L -// AARCH64:#define __INTPTR_TYPE__ long int -// AARCH64:#define __INTPTR_WIDTH__ 64 -// AARCH64:#define __INT_FAST16_FMTd__ "hd" -// AARCH64:#define __INT_FAST16_FMTi__ "hi" -// AARCH64:#define __INT_FAST16_MAX__ 32767 -// AARCH64:#define __INT_FAST16_TYPE__ short -// AARCH64:#define __INT_FAST32_FMTd__ "d" -// AARCH64:#define __INT_FAST32_FMTi__ "i" -// AARCH64:#define __INT_FAST32_MAX__ 2147483647 -// AARCH64:#define __INT_FAST32_TYPE__ int -// AARCH64:#define __INT_FAST64_FMTd__ "ld" -// AARCH64:#define __INT_FAST64_FMTi__ "li" -// AARCH64:#define __INT_FAST64_MAX__ 9223372036854775807L -// AARCH64:#define __INT_FAST64_TYPE__ long int -// AARCH64:#define __INT_FAST8_FMTd__ "hhd" -// AARCH64:#define __INT_FAST8_FMTi__ "hhi" -// AARCH64:#define __INT_FAST8_MAX__ 127 -// AARCH64:#define __INT_FAST8_TYPE__ signed char -// AARCH64:#define __INT_LEAST16_FMTd__ "hd" -// AARCH64:#define __INT_LEAST16_FMTi__ "hi" -// AARCH64:#define __INT_LEAST16_MAX__ 32767 -// AARCH64:#define __INT_LEAST16_TYPE__ short -// AARCH64:#define __INT_LEAST32_FMTd__ "d" -// AARCH64:#define __INT_LEAST32_FMTi__ "i" -// AARCH64:#define __INT_LEAST32_MAX__ 2147483647 -// AARCH64:#define __INT_LEAST32_TYPE__ int -// AARCH64:#define __INT_LEAST64_FMTd__ "ld" -// AARCH64:#define __INT_LEAST64_FMTi__ "li" -// AARCH64:#define __INT_LEAST64_MAX__ 9223372036854775807L -// AARCH64:#define __INT_LEAST64_TYPE__ long int -// AARCH64:#define __INT_LEAST8_FMTd__ "hhd" -// AARCH64:#define __INT_LEAST8_FMTi__ "hhi" -// AARCH64:#define __INT_LEAST8_MAX__ 127 -// AARCH64:#define __INT_LEAST8_TYPE__ signed char -// AARCH64:#define __INT_MAX__ 2147483647 -// AARCH64:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// AARCH64:#define __LDBL_DIG__ 33 -// AARCH64:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// AARCH64:#define __LDBL_HAS_DENORM__ 1 -// AARCH64:#define __LDBL_HAS_INFINITY__ 1 -// AARCH64:#define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64:#define __LDBL_MANT_DIG__ 113 -// AARCH64:#define __LDBL_MAX_10_EXP__ 4932 -// AARCH64:#define __LDBL_MAX_EXP__ 16384 -// AARCH64:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// AARCH64:#define __LDBL_MIN_10_EXP__ (-4931) -// AARCH64:#define __LDBL_MIN_EXP__ (-16381) -// AARCH64:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// AARCH64:#define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64:#define __LONG_MAX__ 9223372036854775807L -// AARCH64:#define __LP64__ 1 -// AARCH64:#define __POINTER_WIDTH__ 64 -// AARCH64:#define __PTRDIFF_TYPE__ long int -// AARCH64:#define __PTRDIFF_WIDTH__ 64 -// AARCH64:#define __SCHAR_MAX__ 127 -// AARCH64:#define __SHRT_MAX__ 32767 -// AARCH64:#define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64:#define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64:#define __SIZEOF_DOUBLE__ 8 -// AARCH64:#define __SIZEOF_FLOAT__ 4 -// AARCH64:#define __SIZEOF_INT128__ 16 -// AARCH64:#define __SIZEOF_INT__ 4 -// AARCH64:#define __SIZEOF_LONG_DOUBLE__ 16 -// AARCH64:#define __SIZEOF_LONG_LONG__ 8 -// AARCH64:#define __SIZEOF_LONG__ 8 -// AARCH64:#define __SIZEOF_POINTER__ 8 -// AARCH64:#define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64:#define __SIZEOF_SHORT__ 2 -// AARCH64:#define __SIZEOF_SIZE_T__ 8 -// AARCH64:#define __SIZEOF_WCHAR_T__ 4 -// AARCH64:#define __SIZEOF_WINT_T__ 4 -// AARCH64:#define __SIZE_MAX__ 18446744073709551615UL -// AARCH64:#define __SIZE_TYPE__ long unsigned int -// AARCH64:#define __SIZE_WIDTH__ 64 -// AARCH64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL -// AARCH64:#define __UINT16_C_SUFFIX__ -// AARCH64:#define __UINT16_MAX__ 65535 -// AARCH64:#define __UINT16_TYPE__ unsigned short -// AARCH64:#define __UINT32_C_SUFFIX__ U -// AARCH64:#define __UINT32_MAX__ 4294967295U -// AARCH64:#define __UINT32_TYPE__ unsigned int -// AARCH64:#define __UINT64_C_SUFFIX__ UL -// AARCH64:#define __UINT64_MAX__ 18446744073709551615UL -// AARCH64:#define __UINT64_TYPE__ long unsigned int -// AARCH64:#define __UINT8_C_SUFFIX__ -// AARCH64:#define __UINT8_MAX__ 255 -// AARCH64:#define __UINT8_TYPE__ unsigned char -// AARCH64:#define __UINTMAX_C_SUFFIX__ UL -// AARCH64:#define __UINTMAX_MAX__ 18446744073709551615UL -// AARCH64:#define __UINTMAX_TYPE__ long unsigned int -// AARCH64:#define __UINTMAX_WIDTH__ 64 -// AARCH64:#define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64:#define __UINTPTR_TYPE__ long unsigned int -// AARCH64:#define __UINTPTR_WIDTH__ 64 -// AARCH64:#define __UINT_FAST16_MAX__ 65535 -// AARCH64:#define __UINT_FAST16_TYPE__ unsigned short -// AARCH64:#define __UINT_FAST32_MAX__ 4294967295U -// AARCH64:#define __UINT_FAST32_TYPE__ unsigned int -// AARCH64:#define __UINT_FAST64_MAX__ 18446744073709551615UL -// AARCH64:#define __UINT_FAST64_TYPE__ long unsigned int -// AARCH64:#define __UINT_FAST8_MAX__ 255 -// AARCH64:#define __UINT_FAST8_TYPE__ unsigned char -// AARCH64:#define __UINT_LEAST16_MAX__ 65535 -// AARCH64:#define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64:#define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64:#define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64:#define __UINT_LEAST64_MAX__ 18446744073709551615UL -// AARCH64:#define __UINT_LEAST64_TYPE__ long unsigned int -// AARCH64:#define __UINT_LEAST8_MAX__ 255 -// AARCH64:#define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64:#define __USER_LABEL_PREFIX__ -// AARCH64:#define __WCHAR_MAX__ 4294967295U -// AARCH64:#define __WCHAR_TYPE__ unsigned int -// AARCH64:#define __WCHAR_UNSIGNED__ 1 -// AARCH64:#define __WCHAR_WIDTH__ 32 -// AARCH64:#define __WINT_TYPE__ int -// AARCH64:#define __WINT_WIDTH__ 32 -// AARCH64:#define __aarch64__ 1 -// -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64_be-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-BE %s -// -// AARCH64-BE:#define _LP64 1 -// AARCH64-BE:#define __AARCH64EB__ 1 -// AARCH64-BE-NOT:#define __AARCH64EL__ 1 -// AARCH64-BE:#define __AARCH_BIG_ENDIAN 1 -// AARCH64-BE:#define __ARM_64BIT_STATE 1 -// AARCH64-BE:#define __ARM_ARCH 8 -// AARCH64-BE:#define __ARM_ARCH_ISA_A64 1 -// AARCH64-BE:#define __ARM_BIG_ENDIAN 1 -// AARCH64-BE:#define __BIGGEST_ALIGNMENT__ 16 -// AARCH64-BE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ -// AARCH64-BE:#define __CHAR16_TYPE__ unsigned short -// AARCH64-BE:#define __CHAR32_TYPE__ unsigned int -// AARCH64-BE:#define __CHAR_BIT__ 8 -// AARCH64-BE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-BE:#define __DBL_DIG__ 15 -// AARCH64-BE:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-BE:#define __DBL_HAS_DENORM__ 1 -// AARCH64-BE:#define __DBL_HAS_INFINITY__ 1 -// AARCH64-BE:#define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-BE:#define __DBL_MANT_DIG__ 53 -// AARCH64-BE:#define __DBL_MAX_10_EXP__ 308 -// AARCH64-BE:#define __DBL_MAX_EXP__ 1024 -// AARCH64-BE:#define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-BE:#define __DBL_MIN_10_EXP__ (-307) -// AARCH64-BE:#define __DBL_MIN_EXP__ (-1021) -// AARCH64-BE:#define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-BE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-BE:#define __FLT_DIG__ 6 -// AARCH64-BE:#define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-BE:#define __FLT_EVAL_METHOD__ 0 -// AARCH64-BE:#define __FLT_HAS_DENORM__ 1 -// AARCH64-BE:#define __FLT_HAS_INFINITY__ 1 -// AARCH64-BE:#define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-BE:#define __FLT_MANT_DIG__ 24 -// AARCH64-BE:#define __FLT_MAX_10_EXP__ 38 -// AARCH64-BE:#define __FLT_MAX_EXP__ 128 -// AARCH64-BE:#define __FLT_MAX__ 3.40282347e+38F -// AARCH64-BE:#define __FLT_MIN_10_EXP__ (-37) -// AARCH64-BE:#define __FLT_MIN_EXP__ (-125) -// AARCH64-BE:#define __FLT_MIN__ 1.17549435e-38F -// AARCH64-BE:#define __FLT_RADIX__ 2 -// AARCH64-BE:#define __INT16_C_SUFFIX__ -// AARCH64-BE:#define __INT16_FMTd__ "hd" -// AARCH64-BE:#define __INT16_FMTi__ "hi" -// AARCH64-BE:#define __INT16_MAX__ 32767 -// AARCH64-BE:#define __INT16_TYPE__ short -// AARCH64-BE:#define __INT32_C_SUFFIX__ -// AARCH64-BE:#define __INT32_FMTd__ "d" -// AARCH64-BE:#define __INT32_FMTi__ "i" -// AARCH64-BE:#define __INT32_MAX__ 2147483647 -// AARCH64-BE:#define __INT32_TYPE__ int -// AARCH64-BE:#define __INT64_C_SUFFIX__ L -// AARCH64-BE:#define __INT64_FMTd__ "ld" -// AARCH64-BE:#define __INT64_FMTi__ "li" -// AARCH64-BE:#define __INT64_MAX__ 9223372036854775807L -// AARCH64-BE:#define __INT64_TYPE__ long int -// AARCH64-BE:#define __INT8_C_SUFFIX__ -// AARCH64-BE:#define __INT8_FMTd__ "hhd" -// AARCH64-BE:#define __INT8_FMTi__ "hhi" -// AARCH64-BE:#define __INT8_MAX__ 127 -// AARCH64-BE:#define __INT8_TYPE__ signed char -// AARCH64-BE:#define __INTMAX_C_SUFFIX__ L -// AARCH64-BE:#define __INTMAX_FMTd__ "ld" -// AARCH64-BE:#define __INTMAX_FMTi__ "li" -// AARCH64-BE:#define __INTMAX_MAX__ 9223372036854775807L -// AARCH64-BE:#define __INTMAX_TYPE__ long int -// AARCH64-BE:#define __INTMAX_WIDTH__ 64 -// AARCH64-BE:#define __INTPTR_FMTd__ "ld" -// AARCH64-BE:#define __INTPTR_FMTi__ "li" -// AARCH64-BE:#define __INTPTR_MAX__ 9223372036854775807L -// AARCH64-BE:#define __INTPTR_TYPE__ long int -// AARCH64-BE:#define __INTPTR_WIDTH__ 64 -// AARCH64-BE:#define __INT_FAST16_FMTd__ "hd" -// AARCH64-BE:#define __INT_FAST16_FMTi__ "hi" -// AARCH64-BE:#define __INT_FAST16_MAX__ 32767 -// AARCH64-BE:#define __INT_FAST16_TYPE__ short -// AARCH64-BE:#define __INT_FAST32_FMTd__ "d" -// AARCH64-BE:#define __INT_FAST32_FMTi__ "i" -// AARCH64-BE:#define __INT_FAST32_MAX__ 2147483647 -// AARCH64-BE:#define __INT_FAST32_TYPE__ int -// AARCH64-BE:#define __INT_FAST64_FMTd__ "ld" -// AARCH64-BE:#define __INT_FAST64_FMTi__ "li" -// AARCH64-BE:#define __INT_FAST64_MAX__ 9223372036854775807L -// AARCH64-BE:#define __INT_FAST64_TYPE__ long int -// AARCH64-BE:#define __INT_FAST8_FMTd__ "hhd" -// AARCH64-BE:#define __INT_FAST8_FMTi__ "hhi" -// AARCH64-BE:#define __INT_FAST8_MAX__ 127 -// AARCH64-BE:#define __INT_FAST8_TYPE__ signed char -// AARCH64-BE:#define __INT_LEAST16_FMTd__ "hd" -// AARCH64-BE:#define __INT_LEAST16_FMTi__ "hi" -// AARCH64-BE:#define __INT_LEAST16_MAX__ 32767 -// AARCH64-BE:#define __INT_LEAST16_TYPE__ short -// AARCH64-BE:#define __INT_LEAST32_FMTd__ "d" -// AARCH64-BE:#define __INT_LEAST32_FMTi__ "i" -// AARCH64-BE:#define __INT_LEAST32_MAX__ 2147483647 -// AARCH64-BE:#define __INT_LEAST32_TYPE__ int -// AARCH64-BE:#define __INT_LEAST64_FMTd__ "ld" -// AARCH64-BE:#define __INT_LEAST64_FMTi__ "li" -// AARCH64-BE:#define __INT_LEAST64_MAX__ 9223372036854775807L -// AARCH64-BE:#define __INT_LEAST64_TYPE__ long int -// AARCH64-BE:#define __INT_LEAST8_FMTd__ "hhd" -// AARCH64-BE:#define __INT_LEAST8_FMTi__ "hhi" -// AARCH64-BE:#define __INT_LEAST8_MAX__ 127 -// AARCH64-BE:#define __INT_LEAST8_TYPE__ signed char -// AARCH64-BE:#define __INT_MAX__ 2147483647 -// AARCH64-BE:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// AARCH64-BE:#define __LDBL_DIG__ 33 -// AARCH64-BE:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// AARCH64-BE:#define __LDBL_HAS_DENORM__ 1 -// AARCH64-BE:#define __LDBL_HAS_INFINITY__ 1 -// AARCH64-BE:#define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-BE:#define __LDBL_MANT_DIG__ 113 -// AARCH64-BE:#define __LDBL_MAX_10_EXP__ 4932 -// AARCH64-BE:#define __LDBL_MAX_EXP__ 16384 -// AARCH64-BE:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// AARCH64-BE:#define __LDBL_MIN_10_EXP__ (-4931) -// AARCH64-BE:#define __LDBL_MIN_EXP__ (-16381) -// AARCH64-BE:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// AARCH64-BE:#define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-BE:#define __LONG_MAX__ 9223372036854775807L -// AARCH64-BE:#define __LP64__ 1 -// AARCH64-BE:#define __POINTER_WIDTH__ 64 -// AARCH64-BE:#define __PTRDIFF_TYPE__ long int -// AARCH64-BE:#define __PTRDIFF_WIDTH__ 64 -// AARCH64-BE:#define __SCHAR_MAX__ 127 -// AARCH64-BE:#define __SHRT_MAX__ 32767 -// AARCH64-BE:#define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-BE:#define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-BE:#define __SIZEOF_DOUBLE__ 8 -// AARCH64-BE:#define __SIZEOF_FLOAT__ 4 -// AARCH64-BE:#define __SIZEOF_INT128__ 16 -// AARCH64-BE:#define __SIZEOF_INT__ 4 -// AARCH64-BE:#define __SIZEOF_LONG_DOUBLE__ 16 -// AARCH64-BE:#define __SIZEOF_LONG_LONG__ 8 -// AARCH64-BE:#define __SIZEOF_LONG__ 8 -// AARCH64-BE:#define __SIZEOF_POINTER__ 8 -// AARCH64-BE:#define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-BE:#define __SIZEOF_SHORT__ 2 -// AARCH64-BE:#define __SIZEOF_SIZE_T__ 8 -// AARCH64-BE:#define __SIZEOF_WCHAR_T__ 4 -// AARCH64-BE:#define __SIZEOF_WINT_T__ 4 -// AARCH64-BE:#define __SIZE_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __SIZE_TYPE__ long unsigned int -// AARCH64-BE:#define __SIZE_WIDTH__ 64 -// AARCH64-BE:#define __UINT16_C_SUFFIX__ -// AARCH64-BE:#define __UINT16_MAX__ 65535 -// AARCH64-BE:#define __UINT16_TYPE__ unsigned short -// AARCH64-BE:#define __UINT32_C_SUFFIX__ U -// AARCH64-BE:#define __UINT32_MAX__ 4294967295U -// AARCH64-BE:#define __UINT32_TYPE__ unsigned int -// AARCH64-BE:#define __UINT64_C_SUFFIX__ UL -// AARCH64-BE:#define __UINT64_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __UINT64_TYPE__ long unsigned int -// AARCH64-BE:#define __UINT8_C_SUFFIX__ -// AARCH64-BE:#define __UINT8_MAX__ 255 -// AARCH64-BE:#define __UINT8_TYPE__ unsigned char -// AARCH64-BE:#define __UINTMAX_C_SUFFIX__ UL -// AARCH64-BE:#define __UINTMAX_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __UINTMAX_TYPE__ long unsigned int -// AARCH64-BE:#define __UINTMAX_WIDTH__ 64 -// AARCH64-BE:#define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __UINTPTR_TYPE__ long unsigned int -// AARCH64-BE:#define __UINTPTR_WIDTH__ 64 -// AARCH64-BE:#define __UINT_FAST16_MAX__ 65535 -// AARCH64-BE:#define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-BE:#define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-BE:#define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-BE:#define __UINT_FAST64_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __UINT_FAST64_TYPE__ long unsigned int -// AARCH64-BE:#define __UINT_FAST8_MAX__ 255 -// AARCH64-BE:#define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-BE:#define __UINT_LEAST16_MAX__ 65535 -// AARCH64-BE:#define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-BE:#define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-BE:#define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-BE:#define __UINT_LEAST64_MAX__ 18446744073709551615UL -// AARCH64-BE:#define __UINT_LEAST64_TYPE__ long unsigned int -// AARCH64-BE:#define __UINT_LEAST8_MAX__ 255 -// AARCH64-BE:#define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-BE:#define __USER_LABEL_PREFIX__ -// AARCH64-BE:#define __WCHAR_MAX__ 4294967295U -// AARCH64-BE:#define __WCHAR_TYPE__ unsigned int -// AARCH64-BE:#define __WCHAR_UNSIGNED__ 1 -// AARCH64-BE:#define __WCHAR_WIDTH__ 32 -// AARCH64-BE:#define __WINT_TYPE__ int -// AARCH64-BE:#define __WINT_WIDTH__ 32 -// AARCH64-BE:#define __aarch64__ 1 -// -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-NETBSD %s -// -// AARCH64-NETBSD:#define _LP64 1 -// AARCH64-NETBSD-NOT:#define __AARCH64EB__ 1 -// AARCH64-NETBSD:#define __AARCH64EL__ 1 -// AARCH64-NETBSD-NOT:#define __AARCH_BIG_ENDIAN 1 -// AARCH64-NETBSD:#define __ARM_64BIT_STATE 1 -// AARCH64-NETBSD:#define __ARM_ARCH 8 -// AARCH64-NETBSD:#define __ARM_ARCH_ISA_A64 1 -// AARCH64-NETBSD-NOT:#define __ARM_BIG_ENDIAN 1 -// AARCH64-NETBSD:#define __BIGGEST_ALIGNMENT__ 16 -// AARCH64-NETBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64-NETBSD:#define __CHAR16_TYPE__ unsigned short -// AARCH64-NETBSD:#define __CHAR32_TYPE__ unsigned int -// AARCH64-NETBSD:#define __CHAR_BIT__ 8 -// AARCH64-NETBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-NETBSD:#define __DBL_DIG__ 15 -// AARCH64-NETBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-NETBSD:#define __DBL_HAS_DENORM__ 1 -// AARCH64-NETBSD:#define __DBL_HAS_INFINITY__ 1 -// AARCH64-NETBSD:#define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-NETBSD:#define __DBL_MANT_DIG__ 53 -// AARCH64-NETBSD:#define __DBL_MAX_10_EXP__ 308 -// AARCH64-NETBSD:#define __DBL_MAX_EXP__ 1024 -// AARCH64-NETBSD:#define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-NETBSD:#define __DBL_MIN_10_EXP__ (-307) -// AARCH64-NETBSD:#define __DBL_MIN_EXP__ (-1021) -// AARCH64-NETBSD:#define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-NETBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-NETBSD:#define __ELF__ 1 -// AARCH64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-NETBSD:#define __FLT_DIG__ 6 -// AARCH64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-NETBSD:#define __FLT_EVAL_METHOD__ 0 -// AARCH64-NETBSD:#define __FLT_HAS_DENORM__ 1 -// AARCH64-NETBSD:#define __FLT_HAS_INFINITY__ 1 -// AARCH64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-NETBSD:#define __FLT_MANT_DIG__ 24 -// AARCH64-NETBSD:#define __FLT_MAX_10_EXP__ 38 -// AARCH64-NETBSD:#define __FLT_MAX_EXP__ 128 -// AARCH64-NETBSD:#define __FLT_MAX__ 3.40282347e+38F -// AARCH64-NETBSD:#define __FLT_MIN_10_EXP__ (-37) -// AARCH64-NETBSD:#define __FLT_MIN_EXP__ (-125) -// AARCH64-NETBSD:#define __FLT_MIN__ 1.17549435e-38F -// AARCH64-NETBSD:#define __FLT_RADIX__ 2 -// AARCH64-NETBSD:#define __INT16_C_SUFFIX__ -// AARCH64-NETBSD:#define __INT16_FMTd__ "hd" -// AARCH64-NETBSD:#define __INT16_FMTi__ "hi" -// AARCH64-NETBSD:#define __INT16_MAX__ 32767 -// AARCH64-NETBSD:#define __INT16_TYPE__ short -// AARCH64-NETBSD:#define __INT32_C_SUFFIX__ -// AARCH64-NETBSD:#define __INT32_FMTd__ "d" -// AARCH64-NETBSD:#define __INT32_FMTi__ "i" -// AARCH64-NETBSD:#define __INT32_MAX__ 2147483647 -// AARCH64-NETBSD:#define __INT32_TYPE__ int -// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ L -// AARCH64-NETBSD:#define __INT64_FMTd__ "ld" -// AARCH64-NETBSD:#define __INT64_FMTi__ "li" -// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __INT64_TYPE__ long int -// AARCH64-NETBSD:#define __INT8_C_SUFFIX__ -// AARCH64-NETBSD:#define __INT8_FMTd__ "hhd" -// AARCH64-NETBSD:#define __INT8_FMTi__ "hhi" -// AARCH64-NETBSD:#define __INT8_MAX__ 127 -// AARCH64-NETBSD:#define __INT8_TYPE__ signed char -// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ L -// AARCH64-NETBSD:#define __INTMAX_FMTd__ "ld" -// AARCH64-NETBSD:#define __INTMAX_FMTi__ "li" -// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __INTMAX_TYPE__ long int -// AARCH64-NETBSD:#define __INTMAX_WIDTH__ 64 -// AARCH64-NETBSD:#define __INTPTR_FMTd__ "ld" -// AARCH64-NETBSD:#define __INTPTR_FMTi__ "li" -// AARCH64-NETBSD:#define __INTPTR_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __INTPTR_TYPE__ long int -// AARCH64-NETBSD:#define __INTPTR_WIDTH__ 64 -// AARCH64-NETBSD:#define __INT_FAST16_FMTd__ "hd" -// AARCH64-NETBSD:#define __INT_FAST16_FMTi__ "hi" -// AARCH64-NETBSD:#define __INT_FAST16_MAX__ 32767 -// AARCH64-NETBSD:#define __INT_FAST16_TYPE__ short -// AARCH64-NETBSD:#define __INT_FAST32_FMTd__ "d" -// AARCH64-NETBSD:#define __INT_FAST32_FMTi__ "i" -// AARCH64-NETBSD:#define __INT_FAST32_MAX__ 2147483647 -// AARCH64-NETBSD:#define __INT_FAST32_TYPE__ int -// AARCH64-NETBSD:#define __INT_FAST64_FMTd__ "ld" -// AARCH64-NETBSD:#define __INT_FAST64_FMTi__ "li" -// AARCH64-NETBSD:#define __INT_FAST64_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __INT_FAST64_TYPE__ long int -// AARCH64-NETBSD:#define __INT_FAST8_FMTd__ "hhd" -// AARCH64-NETBSD:#define __INT_FAST8_FMTi__ "hhi" -// AARCH64-NETBSD:#define __INT_FAST8_MAX__ 127 -// AARCH64-NETBSD:#define __INT_FAST8_TYPE__ signed char -// AARCH64-NETBSD:#define __INT_LEAST16_FMTd__ "hd" -// AARCH64-NETBSD:#define __INT_LEAST16_FMTi__ "hi" -// AARCH64-NETBSD:#define __INT_LEAST16_MAX__ 32767 -// AARCH64-NETBSD:#define __INT_LEAST16_TYPE__ short -// AARCH64-NETBSD:#define __INT_LEAST32_FMTd__ "d" -// AARCH64-NETBSD:#define __INT_LEAST32_FMTi__ "i" -// AARCH64-NETBSD:#define __INT_LEAST32_MAX__ 2147483647 -// AARCH64-NETBSD:#define __INT_LEAST32_TYPE__ int -// AARCH64-NETBSD:#define __INT_LEAST64_FMTd__ "ld" -// AARCH64-NETBSD:#define __INT_LEAST64_FMTi__ "li" -// AARCH64-NETBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __INT_LEAST64_TYPE__ long int -// AARCH64-NETBSD:#define __INT_LEAST8_FMTd__ "hhd" -// AARCH64-NETBSD:#define __INT_LEAST8_FMTi__ "hhi" -// AARCH64-NETBSD:#define __INT_LEAST8_MAX__ 127 -// AARCH64-NETBSD:#define __INT_LEAST8_TYPE__ signed char -// AARCH64-NETBSD:#define __INT_MAX__ 2147483647 -// AARCH64-NETBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// AARCH64-NETBSD:#define __LDBL_DIG__ 33 -// AARCH64-NETBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// AARCH64-NETBSD:#define __LDBL_HAS_DENORM__ 1 -// AARCH64-NETBSD:#define __LDBL_HAS_INFINITY__ 1 -// AARCH64-NETBSD:#define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-NETBSD:#define __LDBL_MANT_DIG__ 113 -// AARCH64-NETBSD:#define __LDBL_MAX_10_EXP__ 4932 -// AARCH64-NETBSD:#define __LDBL_MAX_EXP__ 16384 -// AARCH64-NETBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// AARCH64-NETBSD:#define __LDBL_MIN_10_EXP__ (-4931) -// AARCH64-NETBSD:#define __LDBL_MIN_EXP__ (-16381) -// AARCH64-NETBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// AARCH64-NETBSD:#define __LITTLE_ENDIAN__ 1 -// AARCH64-NETBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-NETBSD:#define __LONG_MAX__ 9223372036854775807L -// AARCH64-NETBSD:#define __LP64__ 1 -// AARCH64-NETBSD:#define __NetBSD__ 1 -// AARCH64-NETBSD:#define __POINTER_WIDTH__ 64 -// AARCH64-NETBSD:#define __PTRDIFF_TYPE__ long int -// AARCH64-NETBSD:#define __PTRDIFF_WIDTH__ 64 -// AARCH64-NETBSD:#define __SCHAR_MAX__ 127 -// AARCH64-NETBSD:#define __SHRT_MAX__ 32767 -// AARCH64-NETBSD:#define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-NETBSD:#define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-NETBSD:#define __SIZEOF_DOUBLE__ 8 -// AARCH64-NETBSD:#define __SIZEOF_FLOAT__ 4 -// AARCH64-NETBSD:#define __SIZEOF_INT__ 4 -// AARCH64-NETBSD:#define __SIZEOF_LONG_DOUBLE__ 16 -// AARCH64-NETBSD:#define __SIZEOF_LONG_LONG__ 8 -// AARCH64-NETBSD:#define __SIZEOF_LONG__ 8 -// AARCH64-NETBSD:#define __SIZEOF_POINTER__ 8 -// AARCH64-NETBSD:#define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-NETBSD:#define __SIZEOF_SHORT__ 2 -// AARCH64-NETBSD:#define __SIZEOF_SIZE_T__ 8 -// AARCH64-NETBSD:#define __SIZEOF_WCHAR_T__ 4 -// AARCH64-NETBSD:#define __SIZEOF_WINT_T__ 4 -// AARCH64-NETBSD:#define __SIZE_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __SIZE_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __SIZE_WIDTH__ 64 -// AARCH64-NETBSD:#define __UINT16_C_SUFFIX__ -// AARCH64-NETBSD:#define __UINT16_MAX__ 65535 -// AARCH64-NETBSD:#define __UINT16_TYPE__ unsigned short -// AARCH64-NETBSD:#define __UINT32_C_SUFFIX__ U -// AARCH64-NETBSD:#define __UINT32_MAX__ 4294967295U -// AARCH64-NETBSD:#define __UINT32_TYPE__ unsigned int -// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ UL -// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __UINT64_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __UINT8_C_SUFFIX__ -// AARCH64-NETBSD:#define __UINT8_MAX__ 255 -// AARCH64-NETBSD:#define __UINT8_TYPE__ unsigned char -// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ UL -// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __UINTMAX_WIDTH__ 64 -// AARCH64-NETBSD:#define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __UINTPTR_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __UINTPTR_WIDTH__ 64 -// AARCH64-NETBSD:#define __UINT_FAST16_MAX__ 65535 -// AARCH64-NETBSD:#define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-NETBSD:#define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-NETBSD:#define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-NETBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __UINT_FAST64_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __UINT_FAST8_MAX__ 255 -// AARCH64-NETBSD:#define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-NETBSD:#define __UINT_LEAST16_MAX__ 65535 -// AARCH64-NETBSD:#define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-NETBSD:#define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-NETBSD:#define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-NETBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL -// AARCH64-NETBSD:#define __UINT_LEAST64_TYPE__ long unsigned int -// AARCH64-NETBSD:#define __UINT_LEAST8_MAX__ 255 -// AARCH64-NETBSD:#define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-NETBSD:#define __USER_LABEL_PREFIX__ -// AARCH64-NETBSD:#define __WCHAR_MAX__ 2147483647 -// AARCH64-NETBSD:#define __WCHAR_TYPE__ int -// AARCH64-NETBSD:#define __WCHAR_WIDTH__ 32 -// AARCH64-NETBSD:#define __WINT_TYPE__ int -// AARCH64-NETBSD:#define __WINT_WIDTH__ 32 -// AARCH64-NETBSD:#define __aarch64__ 1 -// -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-OPENBSD %s -// -// AARCH64-OPENBSD:#define _LP64 1 -// AARCH64-OPENBSD-NOT:#define __AARCH64EB__ 1 -// AARCH64-OPENBSD:#define __AARCH64EL__ 1 -// AARCH64-OPENBSD-NOT:#define __AARCH_BIG_ENDIAN 1 -// AARCH64-OPENBSD:#define __ARM_64BIT_STATE 1 -// AARCH64-OPENBSD:#define __ARM_ARCH 8 -// AARCH64-OPENBSD:#define __ARM_ARCH_ISA_A64 1 -// AARCH64-OPENBSD-NOT:#define __ARM_BIG_ENDIAN 1 -// AARCH64-OPENBSD:#define __BIGGEST_ALIGNMENT__ 16 -// AARCH64-OPENBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64-OPENBSD:#define __CHAR16_TYPE__ unsigned short -// AARCH64-OPENBSD:#define __CHAR32_TYPE__ unsigned int -// AARCH64-OPENBSD:#define __CHAR_BIT__ 8 -// AARCH64-OPENBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-OPENBSD:#define __DBL_DIG__ 15 -// AARCH64-OPENBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-OPENBSD:#define __DBL_HAS_DENORM__ 1 -// AARCH64-OPENBSD:#define __DBL_HAS_INFINITY__ 1 -// AARCH64-OPENBSD:#define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-OPENBSD:#define __DBL_MANT_DIG__ 53 -// AARCH64-OPENBSD:#define __DBL_MAX_10_EXP__ 308 -// AARCH64-OPENBSD:#define __DBL_MAX_EXP__ 1024 -// AARCH64-OPENBSD:#define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-OPENBSD:#define __DBL_MIN_10_EXP__ (-307) -// AARCH64-OPENBSD:#define __DBL_MIN_EXP__ (-1021) -// AARCH64-OPENBSD:#define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-OPENBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-OPENBSD:#define __ELF__ 1 -// AARCH64-OPENBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-OPENBSD:#define __FLT_DIG__ 6 -// AARCH64-OPENBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-OPENBSD:#define __FLT_EVAL_METHOD__ 0 -// AARCH64-OPENBSD:#define __FLT_HAS_DENORM__ 1 -// AARCH64-OPENBSD:#define __FLT_HAS_INFINITY__ 1 -// AARCH64-OPENBSD:#define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-OPENBSD:#define __FLT_MANT_DIG__ 24 -// AARCH64-OPENBSD:#define __FLT_MAX_10_EXP__ 38 -// AARCH64-OPENBSD:#define __FLT_MAX_EXP__ 128 -// AARCH64-OPENBSD:#define __FLT_MAX__ 3.40282347e+38F -// AARCH64-OPENBSD:#define __FLT_MIN_10_EXP__ (-37) -// AARCH64-OPENBSD:#define __FLT_MIN_EXP__ (-125) -// AARCH64-OPENBSD:#define __FLT_MIN__ 1.17549435e-38F -// AARCH64-OPENBSD:#define __FLT_RADIX__ 2 -// AARCH64-OPENBSD:#define __INT16_C_SUFFIX__ -// AARCH64-OPENBSD:#define __INT16_FMTd__ "hd" -// AARCH64-OPENBSD:#define __INT16_FMTi__ "hi" -// AARCH64-OPENBSD:#define __INT16_MAX__ 32767 -// AARCH64-OPENBSD:#define __INT16_TYPE__ short -// AARCH64-OPENBSD:#define __INT32_C_SUFFIX__ -// AARCH64-OPENBSD:#define __INT32_FMTd__ "d" -// AARCH64-OPENBSD:#define __INT32_FMTi__ "i" -// AARCH64-OPENBSD:#define __INT32_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __INT32_TYPE__ int -// AARCH64-OPENBSD:#define __INT64_C_SUFFIX__ LL -// AARCH64-OPENBSD:#define __INT64_FMTd__ "lld" -// AARCH64-OPENBSD:#define __INT64_FMTi__ "lli" -// AARCH64-OPENBSD:#define __INT64_MAX__ 9223372036854775807LL -// AARCH64-OPENBSD:#define __INT64_TYPE__ long long int -// AARCH64-OPENBSD:#define __INT8_C_SUFFIX__ -// AARCH64-OPENBSD:#define __INT8_FMTd__ "hhd" -// AARCH64-OPENBSD:#define __INT8_FMTi__ "hhi" -// AARCH64-OPENBSD:#define __INT8_MAX__ 127 -// AARCH64-OPENBSD:#define __INT8_TYPE__ signed char -// AARCH64-OPENBSD:#define __INTMAX_C_SUFFIX__ LL -// AARCH64-OPENBSD:#define __INTMAX_FMTd__ "lld" -// AARCH64-OPENBSD:#define __INTMAX_FMTi__ "lli" -// AARCH64-OPENBSD:#define __INTMAX_MAX__ 9223372036854775807LL -// AARCH64-OPENBSD:#define __INTMAX_TYPE__ long long int -// AARCH64-OPENBSD:#define __INTMAX_WIDTH__ 64 -// AARCH64-OPENBSD:#define __INTPTR_FMTd__ "ld" -// AARCH64-OPENBSD:#define __INTPTR_FMTi__ "li" -// AARCH64-OPENBSD:#define __INTPTR_MAX__ 9223372036854775807L -// AARCH64-OPENBSD:#define __INTPTR_TYPE__ long int -// AARCH64-OPENBSD:#define __INTPTR_WIDTH__ 64 -// AARCH64-OPENBSD:#define __INT_FAST16_FMTd__ "hd" -// AARCH64-OPENBSD:#define __INT_FAST16_FMTi__ "hi" -// AARCH64-OPENBSD:#define __INT_FAST16_MAX__ 32767 -// AARCH64-OPENBSD:#define __INT_FAST16_TYPE__ short -// AARCH64-OPENBSD:#define __INT_FAST32_FMTd__ "d" -// AARCH64-OPENBSD:#define __INT_FAST32_FMTi__ "i" -// AARCH64-OPENBSD:#define __INT_FAST32_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __INT_FAST32_TYPE__ int -// AARCH64-OPENBSD:#define __INT_FAST64_FMTd__ "ld" -// AARCH64-OPENBSD:#define __INT_FAST64_FMTi__ "li" -// AARCH64-OPENBSD:#define __INT_FAST64_MAX__ 9223372036854775807L -// AARCH64-OPENBSD:#define __INT_FAST64_TYPE__ long int -// AARCH64-OPENBSD:#define __INT_FAST8_FMTd__ "hhd" -// AARCH64-OPENBSD:#define __INT_FAST8_FMTi__ "hhi" -// AARCH64-OPENBSD:#define __INT_FAST8_MAX__ 127 -// AARCH64-OPENBSD:#define __INT_FAST8_TYPE__ signed char -// AARCH64-OPENBSD:#define __INT_LEAST16_FMTd__ "hd" -// AARCH64-OPENBSD:#define __INT_LEAST16_FMTi__ "hi" -// AARCH64-OPENBSD:#define __INT_LEAST16_MAX__ 32767 -// AARCH64-OPENBSD:#define __INT_LEAST16_TYPE__ short -// AARCH64-OPENBSD:#define __INT_LEAST32_FMTd__ "d" -// AARCH64-OPENBSD:#define __INT_LEAST32_FMTi__ "i" -// AARCH64-OPENBSD:#define __INT_LEAST32_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __INT_LEAST32_TYPE__ int -// AARCH64-OPENBSD:#define __INT_LEAST64_FMTd__ "ld" -// AARCH64-OPENBSD:#define __INT_LEAST64_FMTi__ "li" -// AARCH64-OPENBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L -// AARCH64-OPENBSD:#define __INT_LEAST64_TYPE__ long int -// AARCH64-OPENBSD:#define __INT_LEAST8_FMTd__ "hhd" -// AARCH64-OPENBSD:#define __INT_LEAST8_FMTi__ "hhi" -// AARCH64-OPENBSD:#define __INT_LEAST8_MAX__ 127 -// AARCH64-OPENBSD:#define __INT_LEAST8_TYPE__ signed char -// AARCH64-OPENBSD:#define __INT_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// AARCH64-OPENBSD:#define __LDBL_DIG__ 33 -// AARCH64-OPENBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// AARCH64-OPENBSD:#define __LDBL_HAS_DENORM__ 1 -// AARCH64-OPENBSD:#define __LDBL_HAS_INFINITY__ 1 -// AARCH64-OPENBSD:#define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-OPENBSD:#define __LDBL_MANT_DIG__ 113 -// AARCH64-OPENBSD:#define __LDBL_MAX_10_EXP__ 4932 -// AARCH64-OPENBSD:#define __LDBL_MAX_EXP__ 16384 -// AARCH64-OPENBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// AARCH64-OPENBSD:#define __LDBL_MIN_10_EXP__ (-4931) -// AARCH64-OPENBSD:#define __LDBL_MIN_EXP__ (-16381) -// AARCH64-OPENBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// AARCH64-OPENBSD:#define __LITTLE_ENDIAN__ 1 -// AARCH64-OPENBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-OPENBSD:#define __LONG_MAX__ 9223372036854775807L -// AARCH64-OPENBSD:#define __LP64__ 1 -// AARCH64-OPENBSD:#define __OpenBSD__ 1 -// AARCH64-OPENBSD:#define __POINTER_WIDTH__ 64 -// AARCH64-OPENBSD:#define __PTRDIFF_TYPE__ long int -// AARCH64-OPENBSD:#define __PTRDIFF_WIDTH__ 64 -// AARCH64-OPENBSD:#define __SCHAR_MAX__ 127 -// AARCH64-OPENBSD:#define __SHRT_MAX__ 32767 -// AARCH64-OPENBSD:#define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-OPENBSD:#define __SIZEOF_DOUBLE__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_FLOAT__ 4 -// AARCH64-OPENBSD:#define __SIZEOF_INT__ 4 -// AARCH64-OPENBSD:#define __SIZEOF_LONG_DOUBLE__ 16 -// AARCH64-OPENBSD:#define __SIZEOF_LONG_LONG__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_LONG__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_POINTER__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_SHORT__ 2 -// AARCH64-OPENBSD:#define __SIZEOF_SIZE_T__ 8 -// AARCH64-OPENBSD:#define __SIZEOF_WCHAR_T__ 4 -// AARCH64-OPENBSD:#define __SIZEOF_WINT_T__ 4 -// AARCH64-OPENBSD:#define __SIZE_MAX__ 18446744073709551615UL -// AARCH64-OPENBSD:#define __SIZE_TYPE__ long unsigned int -// AARCH64-OPENBSD:#define __SIZE_WIDTH__ 64 -// AARCH64-OPENBSD:#define __UINT16_C_SUFFIX__ -// AARCH64-OPENBSD:#define __UINT16_MAX__ 65535 -// AARCH64-OPENBSD:#define __UINT16_TYPE__ unsigned short -// AARCH64-OPENBSD:#define __UINT32_C_SUFFIX__ U -// AARCH64-OPENBSD:#define __UINT32_MAX__ 4294967295U -// AARCH64-OPENBSD:#define __UINT32_TYPE__ unsigned int -// AARCH64-OPENBSD:#define __UINT64_C_SUFFIX__ ULL -// AARCH64-OPENBSD:#define __UINT64_MAX__ 18446744073709551615ULL -// AARCH64-OPENBSD:#define __UINT64_TYPE__ long long unsigned int -// AARCH64-OPENBSD:#define __UINT8_C_SUFFIX__ -// AARCH64-OPENBSD:#define __UINT8_MAX__ 255 -// AARCH64-OPENBSD:#define __UINT8_TYPE__ unsigned char -// AARCH64-OPENBSD:#define __UINTMAX_C_SUFFIX__ ULL -// AARCH64-OPENBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL -// AARCH64-OPENBSD:#define __UINTMAX_TYPE__ long long unsigned int -// AARCH64-OPENBSD:#define __UINTMAX_WIDTH__ 64 -// AARCH64-OPENBSD:#define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64-OPENBSD:#define __UINTPTR_TYPE__ long unsigned int -// AARCH64-OPENBSD:#define __UINTPTR_WIDTH__ 64 -// AARCH64-OPENBSD:#define __UINT_FAST16_MAX__ 65535 -// AARCH64-OPENBSD:#define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-OPENBSD:#define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-OPENBSD:#define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-OPENBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL -// AARCH64-OPENBSD:#define __UINT_FAST64_TYPE__ long unsigned int -// AARCH64-OPENBSD:#define __UINT_FAST8_MAX__ 255 -// AARCH64-OPENBSD:#define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-OPENBSD:#define __UINT_LEAST16_MAX__ 65535 -// AARCH64-OPENBSD:#define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-OPENBSD:#define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-OPENBSD:#define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-OPENBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL -// AARCH64-OPENBSD:#define __UINT_LEAST64_TYPE__ long unsigned int -// AARCH64-OPENBSD:#define __UINT_LEAST8_MAX__ 255 -// AARCH64-OPENBSD:#define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-OPENBSD:#define __USER_LABEL_PREFIX__ -// AARCH64-OPENBSD:#define __WCHAR_MAX__ 2147483647 -// AARCH64-OPENBSD:#define __WCHAR_TYPE__ int -// AARCH64-OPENBSD:#define __WCHAR_WIDTH__ 32 -// AARCH64-OPENBSD:#define __WINT_TYPE__ int -// AARCH64-OPENBSD:#define __WINT_WIDTH__ 32 -// AARCH64-OPENBSD:#define __aarch64__ 1 -// -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-freebsd11 < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-FREEBSD %s -// -// AARCH64-FREEBSD:#define _LP64 1 -// AARCH64-FREEBSD-NOT:#define __AARCH64EB__ 1 -// AARCH64-FREEBSD:#define __AARCH64EL__ 1 -// AARCH64-FREEBSD-NOT:#define __AARCH_BIG_ENDIAN 1 -// AARCH64-FREEBSD:#define __ARM_64BIT_STATE 1 -// AARCH64-FREEBSD:#define __ARM_ARCH 8 -// AARCH64-FREEBSD:#define __ARM_ARCH_ISA_A64 1 -// AARCH64-FREEBSD-NOT:#define __ARM_BIG_ENDIAN 1 -// AARCH64-FREEBSD:#define __BIGGEST_ALIGNMENT__ 16 -// AARCH64-FREEBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64-FREEBSD:#define __CHAR16_TYPE__ unsigned short -// AARCH64-FREEBSD:#define __CHAR32_TYPE__ unsigned int -// AARCH64-FREEBSD:#define __CHAR_BIT__ 8 -// AARCH64-FREEBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-FREEBSD:#define __DBL_DIG__ 15 -// AARCH64-FREEBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-FREEBSD:#define __DBL_HAS_DENORM__ 1 -// AARCH64-FREEBSD:#define __DBL_HAS_INFINITY__ 1 -// AARCH64-FREEBSD:#define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-FREEBSD:#define __DBL_MANT_DIG__ 53 -// AARCH64-FREEBSD:#define __DBL_MAX_10_EXP__ 308 -// AARCH64-FREEBSD:#define __DBL_MAX_EXP__ 1024 -// AARCH64-FREEBSD:#define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-FREEBSD:#define __DBL_MIN_10_EXP__ (-307) -// AARCH64-FREEBSD:#define __DBL_MIN_EXP__ (-1021) -// AARCH64-FREEBSD:#define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-FREEBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-FREEBSD:#define __ELF__ 1 -// AARCH64-FREEBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-FREEBSD:#define __FLT_DIG__ 6 -// AARCH64-FREEBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-FREEBSD:#define __FLT_EVAL_METHOD__ 0 -// AARCH64-FREEBSD:#define __FLT_HAS_DENORM__ 1 -// AARCH64-FREEBSD:#define __FLT_HAS_INFINITY__ 1 -// AARCH64-FREEBSD:#define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-FREEBSD:#define __FLT_MANT_DIG__ 24 -// AARCH64-FREEBSD:#define __FLT_MAX_10_EXP__ 38 -// AARCH64-FREEBSD:#define __FLT_MAX_EXP__ 128 -// AARCH64-FREEBSD:#define __FLT_MAX__ 3.40282347e+38F -// AARCH64-FREEBSD:#define __FLT_MIN_10_EXP__ (-37) -// AARCH64-FREEBSD:#define __FLT_MIN_EXP__ (-125) -// AARCH64-FREEBSD:#define __FLT_MIN__ 1.17549435e-38F -// AARCH64-FREEBSD:#define __FLT_RADIX__ 2 -// AARCH64-FREEBSD:#define __FreeBSD__ 11 -// AARCH64-FREEBSD:#define __INT16_C_SUFFIX__ -// AARCH64-FREEBSD:#define __INT16_FMTd__ "hd" -// AARCH64-FREEBSD:#define __INT16_FMTi__ "hi" -// AARCH64-FREEBSD:#define __INT16_MAX__ 32767 -// AARCH64-FREEBSD:#define __INT16_TYPE__ short -// AARCH64-FREEBSD:#define __INT32_C_SUFFIX__ -// AARCH64-FREEBSD:#define __INT32_FMTd__ "d" -// AARCH64-FREEBSD:#define __INT32_FMTi__ "i" -// AARCH64-FREEBSD:#define __INT32_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __INT32_TYPE__ int -// AARCH64-FREEBSD:#define __INT64_C_SUFFIX__ L -// AARCH64-FREEBSD:#define __INT64_FMTd__ "ld" -// AARCH64-FREEBSD:#define __INT64_FMTi__ "li" -// AARCH64-FREEBSD:#define __INT64_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __INT64_TYPE__ long int -// AARCH64-FREEBSD:#define __INT8_C_SUFFIX__ -// AARCH64-FREEBSD:#define __INT8_FMTd__ "hhd" -// AARCH64-FREEBSD:#define __INT8_FMTi__ "hhi" -// AARCH64-FREEBSD:#define __INT8_MAX__ 127 -// AARCH64-FREEBSD:#define __INT8_TYPE__ signed char -// AARCH64-FREEBSD:#define __INTMAX_C_SUFFIX__ L -// AARCH64-FREEBSD:#define __INTMAX_FMTd__ "ld" -// AARCH64-FREEBSD:#define __INTMAX_FMTi__ "li" -// AARCH64-FREEBSD:#define __INTMAX_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __INTMAX_TYPE__ long int -// AARCH64-FREEBSD:#define __INTMAX_WIDTH__ 64 -// AARCH64-FREEBSD:#define __INTPTR_FMTd__ "ld" -// AARCH64-FREEBSD:#define __INTPTR_FMTi__ "li" -// AARCH64-FREEBSD:#define __INTPTR_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __INTPTR_TYPE__ long int -// AARCH64-FREEBSD:#define __INTPTR_WIDTH__ 64 -// AARCH64-FREEBSD:#define __INT_FAST16_FMTd__ "hd" -// AARCH64-FREEBSD:#define __INT_FAST16_FMTi__ "hi" -// AARCH64-FREEBSD:#define __INT_FAST16_MAX__ 32767 -// AARCH64-FREEBSD:#define __INT_FAST16_TYPE__ short -// AARCH64-FREEBSD:#define __INT_FAST32_FMTd__ "d" -// AARCH64-FREEBSD:#define __INT_FAST32_FMTi__ "i" -// AARCH64-FREEBSD:#define __INT_FAST32_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __INT_FAST32_TYPE__ int -// AARCH64-FREEBSD:#define __INT_FAST64_FMTd__ "ld" -// AARCH64-FREEBSD:#define __INT_FAST64_FMTi__ "li" -// AARCH64-FREEBSD:#define __INT_FAST64_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __INT_FAST64_TYPE__ long int -// AARCH64-FREEBSD:#define __INT_FAST8_FMTd__ "hhd" -// AARCH64-FREEBSD:#define __INT_FAST8_FMTi__ "hhi" -// AARCH64-FREEBSD:#define __INT_FAST8_MAX__ 127 -// AARCH64-FREEBSD:#define __INT_FAST8_TYPE__ signed char -// AARCH64-FREEBSD:#define __INT_LEAST16_FMTd__ "hd" -// AARCH64-FREEBSD:#define __INT_LEAST16_FMTi__ "hi" -// AARCH64-FREEBSD:#define __INT_LEAST16_MAX__ 32767 -// AARCH64-FREEBSD:#define __INT_LEAST16_TYPE__ short -// AARCH64-FREEBSD:#define __INT_LEAST32_FMTd__ "d" -// AARCH64-FREEBSD:#define __INT_LEAST32_FMTi__ "i" -// AARCH64-FREEBSD:#define __INT_LEAST32_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __INT_LEAST32_TYPE__ int -// AARCH64-FREEBSD:#define __INT_LEAST64_FMTd__ "ld" -// AARCH64-FREEBSD:#define __INT_LEAST64_FMTi__ "li" -// AARCH64-FREEBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __INT_LEAST64_TYPE__ long int -// AARCH64-FREEBSD:#define __INT_LEAST8_FMTd__ "hhd" -// AARCH64-FREEBSD:#define __INT_LEAST8_FMTi__ "hhi" -// AARCH64-FREEBSD:#define __INT_LEAST8_MAX__ 127 -// AARCH64-FREEBSD:#define __INT_LEAST8_TYPE__ signed char -// AARCH64-FREEBSD:#define __INT_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// AARCH64-FREEBSD:#define __LDBL_DIG__ 33 -// AARCH64-FREEBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// AARCH64-FREEBSD:#define __LDBL_HAS_DENORM__ 1 -// AARCH64-FREEBSD:#define __LDBL_HAS_INFINITY__ 1 -// AARCH64-FREEBSD:#define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-FREEBSD:#define __LDBL_MANT_DIG__ 113 -// AARCH64-FREEBSD:#define __LDBL_MAX_10_EXP__ 4932 -// AARCH64-FREEBSD:#define __LDBL_MAX_EXP__ 16384 -// AARCH64-FREEBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// AARCH64-FREEBSD:#define __LDBL_MIN_10_EXP__ (-4931) -// AARCH64-FREEBSD:#define __LDBL_MIN_EXP__ (-16381) -// AARCH64-FREEBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// AARCH64-FREEBSD:#define __LITTLE_ENDIAN__ 1 -// AARCH64-FREEBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-FREEBSD:#define __LONG_MAX__ 9223372036854775807L -// AARCH64-FREEBSD:#define __LP64__ 1 -// AARCH64-FREEBSD:#define __POINTER_WIDTH__ 64 -// AARCH64-FREEBSD:#define __PTRDIFF_TYPE__ long int -// AARCH64-FREEBSD:#define __PTRDIFF_WIDTH__ 64 -// AARCH64-FREEBSD:#define __SCHAR_MAX__ 127 -// AARCH64-FREEBSD:#define __SHRT_MAX__ 32767 -// AARCH64-FREEBSD:#define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-FREEBSD:#define __SIZEOF_DOUBLE__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_FLOAT__ 4 -// AARCH64-FREEBSD:#define __SIZEOF_INT128__ 16 -// AARCH64-FREEBSD:#define __SIZEOF_INT__ 4 -// AARCH64-FREEBSD:#define __SIZEOF_LONG_DOUBLE__ 16 -// AARCH64-FREEBSD:#define __SIZEOF_LONG_LONG__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_LONG__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_POINTER__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_SHORT__ 2 -// AARCH64-FREEBSD:#define __SIZEOF_SIZE_T__ 8 -// AARCH64-FREEBSD:#define __SIZEOF_WCHAR_T__ 4 -// AARCH64-FREEBSD:#define __SIZEOF_WINT_T__ 4 -// AARCH64-FREEBSD:#define __SIZE_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __SIZE_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __SIZE_WIDTH__ 64 -// AARCH64-FREEBSD:#define __UINT16_C_SUFFIX__ -// AARCH64-FREEBSD:#define __UINT16_MAX__ 65535 -// AARCH64-FREEBSD:#define __UINT16_TYPE__ unsigned short -// AARCH64-FREEBSD:#define __UINT32_C_SUFFIX__ U -// AARCH64-FREEBSD:#define __UINT32_MAX__ 4294967295U -// AARCH64-FREEBSD:#define __UINT32_TYPE__ unsigned int -// AARCH64-FREEBSD:#define __UINT64_C_SUFFIX__ UL -// AARCH64-FREEBSD:#define __UINT64_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __UINT64_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __UINT8_C_SUFFIX__ -// AARCH64-FREEBSD:#define __UINT8_MAX__ 255 -// AARCH64-FREEBSD:#define __UINT8_TYPE__ unsigned char -// AARCH64-FREEBSD:#define __UINTMAX_C_SUFFIX__ UL -// AARCH64-FREEBSD:#define __UINTMAX_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __UINTMAX_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __UINTMAX_WIDTH__ 64 -// AARCH64-FREEBSD:#define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __UINTPTR_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __UINTPTR_WIDTH__ 64 -// AARCH64-FREEBSD:#define __UINT_FAST16_MAX__ 65535 -// AARCH64-FREEBSD:#define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-FREEBSD:#define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-FREEBSD:#define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-FREEBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __UINT_FAST64_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __UINT_FAST8_MAX__ 255 -// AARCH64-FREEBSD:#define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-FREEBSD:#define __UINT_LEAST16_MAX__ 65535 -// AARCH64-FREEBSD:#define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-FREEBSD:#define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-FREEBSD:#define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-FREEBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL -// AARCH64-FREEBSD:#define __UINT_LEAST64_TYPE__ long unsigned int -// AARCH64-FREEBSD:#define __UINT_LEAST8_MAX__ 255 -// AARCH64-FREEBSD:#define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-FREEBSD:#define __USER_LABEL_PREFIX__ -// AARCH64-FREEBSD:#define __WCHAR_MAX__ 4294967295U -// AARCH64-FREEBSD:#define __WCHAR_TYPE__ unsigned int -// AARCH64-FREEBSD:#define __WCHAR_UNSIGNED__ 1 -// AARCH64-FREEBSD:#define __WCHAR_WIDTH__ 32 -// AARCH64-FREEBSD:#define __WINT_MAX__ 2147483647 -// AARCH64-FREEBSD:#define __WINT_TYPE__ int -// AARCH64-FREEBSD:#define __WINT_WIDTH__ 32 -// AARCH64-FREEBSD:#define __aarch64__ 1 - -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-apple-ios7.0 < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-DARWIN %s -// -// AARCH64-DARWIN: #define _LP64 1 -// AARCH64-DARWIN-NOT: #define __AARCH64EB__ 1 -// AARCH64-DARWIN: #define __AARCH64EL__ 1 -// AARCH64-DARWIN-NOT: #define __AARCH_BIG_ENDIAN 1 -// AARCH64-DARWIN: #define __ARM_64BIT_STATE 1 -// AARCH64-DARWIN: #define __ARM_ARCH 8 -// AARCH64-DARWIN: #define __ARM_ARCH_ISA_A64 1 -// AARCH64-DARWIN-NOT: #define __ARM_BIG_ENDIAN 1 -// AARCH64-DARWIN: #define __BIGGEST_ALIGNMENT__ 8 -// AARCH64-DARWIN: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64-DARWIN: #define __CHAR16_TYPE__ unsigned short -// AARCH64-DARWIN: #define __CHAR32_TYPE__ unsigned int -// AARCH64-DARWIN: #define __CHAR_BIT__ 8 -// AARCH64-DARWIN: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-DARWIN: #define __DBL_DIG__ 15 -// AARCH64-DARWIN: #define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-DARWIN: #define __DBL_HAS_DENORM__ 1 -// AARCH64-DARWIN: #define __DBL_HAS_INFINITY__ 1 -// AARCH64-DARWIN: #define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-DARWIN: #define __DBL_MANT_DIG__ 53 -// AARCH64-DARWIN: #define __DBL_MAX_10_EXP__ 308 -// AARCH64-DARWIN: #define __DBL_MAX_EXP__ 1024 -// AARCH64-DARWIN: #define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-DARWIN: #define __DBL_MIN_10_EXP__ (-307) -// AARCH64-DARWIN: #define __DBL_MIN_EXP__ (-1021) -// AARCH64-DARWIN: #define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-DARWIN: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-DARWIN: #define __FLT_DIG__ 6 -// AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0 -// AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1 -// AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1 -// AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-DARWIN: #define __FLT_MANT_DIG__ 24 -// AARCH64-DARWIN: #define __FLT_MAX_10_EXP__ 38 -// AARCH64-DARWIN: #define __FLT_MAX_EXP__ 128 -// AARCH64-DARWIN: #define __FLT_MAX__ 3.40282347e+38F -// AARCH64-DARWIN: #define __FLT_MIN_10_EXP__ (-37) -// AARCH64-DARWIN: #define __FLT_MIN_EXP__ (-125) -// AARCH64-DARWIN: #define __FLT_MIN__ 1.17549435e-38F -// AARCH64-DARWIN: #define __FLT_RADIX__ 2 -// AARCH64-DARWIN: #define __INT16_C_SUFFIX__ -// AARCH64-DARWIN: #define __INT16_FMTd__ "hd" -// AARCH64-DARWIN: #define __INT16_FMTi__ "hi" -// AARCH64-DARWIN: #define __INT16_MAX__ 32767 -// AARCH64-DARWIN: #define __INT16_TYPE__ short -// AARCH64-DARWIN: #define __INT32_C_SUFFIX__ -// AARCH64-DARWIN: #define __INT32_FMTd__ "d" -// AARCH64-DARWIN: #define __INT32_FMTi__ "i" -// AARCH64-DARWIN: #define __INT32_MAX__ 2147483647 -// AARCH64-DARWIN: #define __INT32_TYPE__ int -// AARCH64-DARWIN: #define __INT64_C_SUFFIX__ LL -// AARCH64-DARWIN: #define __INT64_FMTd__ "lld" -// AARCH64-DARWIN: #define __INT64_FMTi__ "lli" -// AARCH64-DARWIN: #define __INT64_MAX__ 9223372036854775807LL -// AARCH64-DARWIN: #define __INT64_TYPE__ long long int -// AARCH64-DARWIN: #define __INT8_C_SUFFIX__ -// AARCH64-DARWIN: #define __INT8_FMTd__ "hhd" -// AARCH64-DARWIN: #define __INT8_FMTi__ "hhi" -// AARCH64-DARWIN: #define __INT8_MAX__ 127 -// AARCH64-DARWIN: #define __INT8_TYPE__ signed char -// AARCH64-DARWIN: #define __INTMAX_C_SUFFIX__ L -// AARCH64-DARWIN: #define __INTMAX_FMTd__ "ld" -// AARCH64-DARWIN: #define __INTMAX_FMTi__ "li" -// AARCH64-DARWIN: #define __INTMAX_MAX__ 9223372036854775807L -// AARCH64-DARWIN: #define __INTMAX_TYPE__ long int -// AARCH64-DARWIN: #define __INTMAX_WIDTH__ 64 -// AARCH64-DARWIN: #define __INTPTR_FMTd__ "ld" -// AARCH64-DARWIN: #define __INTPTR_FMTi__ "li" -// AARCH64-DARWIN: #define __INTPTR_MAX__ 9223372036854775807L -// AARCH64-DARWIN: #define __INTPTR_TYPE__ long int -// AARCH64-DARWIN: #define __INTPTR_WIDTH__ 64 -// AARCH64-DARWIN: #define __INT_FAST16_FMTd__ "hd" -// AARCH64-DARWIN: #define __INT_FAST16_FMTi__ "hi" -// AARCH64-DARWIN: #define __INT_FAST16_MAX__ 32767 -// AARCH64-DARWIN: #define __INT_FAST16_TYPE__ short -// AARCH64-DARWIN: #define __INT_FAST32_FMTd__ "d" -// AARCH64-DARWIN: #define __INT_FAST32_FMTi__ "i" -// AARCH64-DARWIN: #define __INT_FAST32_MAX__ 2147483647 -// AARCH64-DARWIN: #define __INT_FAST32_TYPE__ int -// AARCH64-DARWIN: #define __INT_FAST64_FMTd__ "lld" -// AARCH64-DARWIN: #define __INT_FAST64_FMTi__ "lli" -// AARCH64-DARWIN: #define __INT_FAST64_MAX__ 9223372036854775807LL -// AARCH64-DARWIN: #define __INT_FAST64_TYPE__ long long int -// AARCH64-DARWIN: #define __INT_FAST8_FMTd__ "hhd" -// AARCH64-DARWIN: #define __INT_FAST8_FMTi__ "hhi" -// AARCH64-DARWIN: #define __INT_FAST8_MAX__ 127 -// AARCH64-DARWIN: #define __INT_FAST8_TYPE__ signed char -// AARCH64-DARWIN: #define __INT_LEAST16_FMTd__ "hd" -// AARCH64-DARWIN: #define __INT_LEAST16_FMTi__ "hi" -// AARCH64-DARWIN: #define __INT_LEAST16_MAX__ 32767 -// AARCH64-DARWIN: #define __INT_LEAST16_TYPE__ short -// AARCH64-DARWIN: #define __INT_LEAST32_FMTd__ "d" -// AARCH64-DARWIN: #define __INT_LEAST32_FMTi__ "i" -// AARCH64-DARWIN: #define __INT_LEAST32_MAX__ 2147483647 -// AARCH64-DARWIN: #define __INT_LEAST32_TYPE__ int -// AARCH64-DARWIN: #define __INT_LEAST64_FMTd__ "lld" -// AARCH64-DARWIN: #define __INT_LEAST64_FMTi__ "lli" -// AARCH64-DARWIN: #define __INT_LEAST64_MAX__ 9223372036854775807LL -// AARCH64-DARWIN: #define __INT_LEAST64_TYPE__ long long int -// AARCH64-DARWIN: #define __INT_LEAST8_FMTd__ "hhd" -// AARCH64-DARWIN: #define __INT_LEAST8_FMTi__ "hhi" -// AARCH64-DARWIN: #define __INT_LEAST8_MAX__ 127 -// AARCH64-DARWIN: #define __INT_LEAST8_TYPE__ signed char -// AARCH64-DARWIN: #define __INT_MAX__ 2147483647 -// AARCH64-DARWIN: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L -// AARCH64-DARWIN: #define __LDBL_DIG__ 15 -// AARCH64-DARWIN: #define __LDBL_EPSILON__ 2.2204460492503131e-16L -// AARCH64-DARWIN: #define __LDBL_HAS_DENORM__ 1 -// AARCH64-DARWIN: #define __LDBL_HAS_INFINITY__ 1 -// AARCH64-DARWIN: #define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-DARWIN: #define __LDBL_MANT_DIG__ 53 -// AARCH64-DARWIN: #define __LDBL_MAX_10_EXP__ 308 -// AARCH64-DARWIN: #define __LDBL_MAX_EXP__ 1024 -// AARCH64-DARWIN: #define __LDBL_MAX__ 1.7976931348623157e+308L -// AARCH64-DARWIN: #define __LDBL_MIN_10_EXP__ (-307) -// AARCH64-DARWIN: #define __LDBL_MIN_EXP__ (-1021) -// AARCH64-DARWIN: #define __LDBL_MIN__ 2.2250738585072014e-308L -// AARCH64-DARWIN: #define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-DARWIN: #define __LONG_MAX__ 9223372036854775807L -// AARCH64-DARWIN: #define __LP64__ 1 -// AARCH64-DARWIN: #define __POINTER_WIDTH__ 64 -// AARCH64-DARWIN: #define __PTRDIFF_TYPE__ long int -// AARCH64-DARWIN: #define __PTRDIFF_WIDTH__ 64 -// AARCH64-DARWIN: #define __SCHAR_MAX__ 127 -// AARCH64-DARWIN: #define __SHRT_MAX__ 32767 -// AARCH64-DARWIN: #define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-DARWIN: #define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-DARWIN: #define __SIZEOF_DOUBLE__ 8 -// AARCH64-DARWIN: #define __SIZEOF_FLOAT__ 4 -// AARCH64-DARWIN: #define __SIZEOF_INT128__ 16 -// AARCH64-DARWIN: #define __SIZEOF_INT__ 4 -// AARCH64-DARWIN: #define __SIZEOF_LONG_DOUBLE__ 8 -// AARCH64-DARWIN: #define __SIZEOF_LONG_LONG__ 8 -// AARCH64-DARWIN: #define __SIZEOF_LONG__ 8 -// AARCH64-DARWIN: #define __SIZEOF_POINTER__ 8 -// AARCH64-DARWIN: #define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-DARWIN: #define __SIZEOF_SHORT__ 2 -// AARCH64-DARWIN: #define __SIZEOF_SIZE_T__ 8 -// AARCH64-DARWIN: #define __SIZEOF_WCHAR_T__ 4 -// AARCH64-DARWIN: #define __SIZEOF_WINT_T__ 4 -// AARCH64-DARWIN: #define __SIZE_MAX__ 18446744073709551615UL -// AARCH64-DARWIN: #define __SIZE_TYPE__ long unsigned int -// AARCH64-DARWIN: #define __SIZE_WIDTH__ 64 -// AARCH64-DARWIN: #define __UINT16_C_SUFFIX__ -// AARCH64-DARWIN: #define __UINT16_MAX__ 65535 -// AARCH64-DARWIN: #define __UINT16_TYPE__ unsigned short -// AARCH64-DARWIN: #define __UINT32_C_SUFFIX__ U -// AARCH64-DARWIN: #define __UINT32_MAX__ 4294967295U -// AARCH64-DARWIN: #define __UINT32_TYPE__ unsigned int -// AARCH64-DARWIN: #define __UINT64_C_SUFFIX__ ULL -// AARCH64-DARWIN: #define __UINT64_MAX__ 18446744073709551615ULL -// AARCH64-DARWIN: #define __UINT64_TYPE__ long long unsigned int -// AARCH64-DARWIN: #define __UINT8_C_SUFFIX__ -// AARCH64-DARWIN: #define __UINT8_MAX__ 255 -// AARCH64-DARWIN: #define __UINT8_TYPE__ unsigned char -// AARCH64-DARWIN: #define __UINTMAX_C_SUFFIX__ UL -// AARCH64-DARWIN: #define __UINTMAX_MAX__ 18446744073709551615UL -// AARCH64-DARWIN: #define __UINTMAX_TYPE__ long unsigned int -// AARCH64-DARWIN: #define __UINTMAX_WIDTH__ 64 -// AARCH64-DARWIN: #define __UINTPTR_MAX__ 18446744073709551615UL -// AARCH64-DARWIN: #define __UINTPTR_TYPE__ long unsigned int -// AARCH64-DARWIN: #define __UINTPTR_WIDTH__ 64 -// AARCH64-DARWIN: #define __UINT_FAST16_MAX__ 65535 -// AARCH64-DARWIN: #define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-DARWIN: #define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-DARWIN: #define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-DARWIN: #define __UINT_FAST64_MAX__ 18446744073709551615ULL -// AARCH64-DARWIN: #define __UINT_FAST64_TYPE__ long long unsigned int -// AARCH64-DARWIN: #define __UINT_FAST8_MAX__ 255 -// AARCH64-DARWIN: #define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-DARWIN: #define __UINT_LEAST16_MAX__ 65535 -// AARCH64-DARWIN: #define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-DARWIN: #define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-DARWIN: #define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-DARWIN: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL -// AARCH64-DARWIN: #define __UINT_LEAST64_TYPE__ long long unsigned int -// AARCH64-DARWIN: #define __UINT_LEAST8_MAX__ 255 -// AARCH64-DARWIN: #define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-DARWIN: #define __USER_LABEL_PREFIX__ _ -// AARCH64-DARWIN: #define __WCHAR_MAX__ 2147483647 -// AARCH64-DARWIN: #define __WCHAR_TYPE__ int -// AARCH64-DARWIN-NOT: #define __WCHAR_UNSIGNED__ -// AARCH64-DARWIN: #define __WCHAR_WIDTH__ 32 -// AARCH64-DARWIN: #define __WINT_TYPE__ int -// AARCH64-DARWIN: #define __WINT_WIDTH__ 32 -// AARCH64-DARWIN: #define __aarch64__ 1 - // RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7-windows-msvc < /dev/null | FileCheck -match-full-lines -check-prefix ARM-MSVC %s // // ARM-MSVC: #define _M_ARM_NT 1 // ARM-MSVC: #define _WIN32 1 // ARM-MSVC-NOT:#define __ARM_DWARF_EH__ 1 -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-windows-msvc < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-MSVC %s -// -// AARCH64-MSVC: #define _INTEGRAL_MAX_BITS 64 -// AARCH64-MSVC-NOT: #define _LP64 1 -// AARCH64-MSVC: #define _M_ARM64 1 -// AARCH64-MSVC: #define _WIN32 1 -// AARCH64-MSVC: #define _WIN64 1 -// AARCH64-MSVC: #define __AARCH64EL__ 1 -// AARCH64-MSVC: #define __ARM_64BIT_STATE 1 -// AARCH64-MSVC: #define __ARM_ACLE 200 -// AARCH64-MSVC: #define __ARM_ALIGN_MAX_STACK_PWR 4 -// AARCH64-MSVC: #define __ARM_ARCH 8 -// AARCH64-MSVC: #define __ARM_ARCH_ISA_A64 1 -// AARCH64-MSVC: #define __ARM_ARCH_PROFILE 'A' -// AARCH64-MSVC: #define __ARM_FEATURE_CLZ 1 -// AARCH64-MSVC: #define __ARM_FEATURE_DIRECTED_ROUNDING 1 -// AARCH64-MSVC: #define __ARM_FEATURE_DIV 1 -// AARCH64-MSVC: #define __ARM_FEATURE_FMA 1 -// AARCH64-MSVC: #define __ARM_FEATURE_IDIV 1 -// AARCH64-MSVC: #define __ARM_FEATURE_LDREX 0xF -// AARCH64-MSVC: #define __ARM_FEATURE_NUMERIC_MAXMIN 1 -// AARCH64-MSVC: #define __ARM_FEATURE_UNALIGNED 1 -// AARCH64-MSVC: #define __ARM_FP 0xE -// AARCH64-MSVC: #define __ARM_FP16_ARGS 1 -// AARCH64-MSVC: #define __ARM_FP16_FORMAT_IEEE 1 -// AARCH64-MSVC: #define __ARM_PCS_AAPCS64 1 -// AARCH64-MSVC: #define __ARM_SIZEOF_MINIMAL_ENUM 4 -// AARCH64-MSVC: #define __ARM_SIZEOF_WCHAR_T 4 -// AARCH64-MSVC: #define __BIGGEST_ALIGNMENT__ 16 -// AARCH64-MSVC: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// AARCH64-MSVC: #define __CHAR16_TYPE__ unsigned short -// AARCH64-MSVC: #define __CHAR32_TYPE__ unsigned int -// AARCH64-MSVC: #define __CHAR_BIT__ 8 -// AARCH64-MSVC: #define __CONSTANT_CFSTRINGS__ 1 -// AARCH64-MSVC: #define __DBL_DECIMAL_DIG__ 17 -// AARCH64-MSVC: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// AARCH64-MSVC: #define __DBL_DIG__ 15 -// AARCH64-MSVC: #define __DBL_EPSILON__ 2.2204460492503131e-16 -// AARCH64-MSVC: #define __DBL_HAS_DENORM__ 1 -// AARCH64-MSVC: #define __DBL_HAS_INFINITY__ 1 -// AARCH64-MSVC: #define __DBL_HAS_QUIET_NAN__ 1 -// AARCH64-MSVC: #define __DBL_MANT_DIG__ 53 -// AARCH64-MSVC: #define __DBL_MAX_10_EXP__ 308 -// AARCH64-MSVC: #define __DBL_MAX_EXP__ 1024 -// AARCH64-MSVC: #define __DBL_MAX__ 1.7976931348623157e+308 -// AARCH64-MSVC: #define __DBL_MIN_10_EXP__ (-307) -// AARCH64-MSVC: #define __DBL_MIN_EXP__ (-1021) -// AARCH64-MSVC: #define __DBL_MIN__ 2.2250738585072014e-308 -// AARCH64-MSVC: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// AARCH64-MSVC: #define __FINITE_MATH_ONLY__ 0 -// AARCH64-MSVC: #define __FLT_DECIMAL_DIG__ 9 -// AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F -// AARCH64-MSVC: #define __FLT_DIG__ 6 -// AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0 -// AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1 -// AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1 -// AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1 -// AARCH64-MSVC: #define __FLT_MANT_DIG__ 24 -// AARCH64-MSVC: #define __FLT_MAX_10_EXP__ 38 -// AARCH64-MSVC: #define __FLT_MAX_EXP__ 128 -// AARCH64-MSVC: #define __FLT_MAX__ 3.40282347e+38F -// AARCH64-MSVC: #define __FLT_MIN_10_EXP__ (-37) -// AARCH64-MSVC: #define __FLT_MIN_EXP__ (-125) -// AARCH64-MSVC: #define __FLT_MIN__ 1.17549435e-38F -// AARCH64-MSVC: #define __FLT_RADIX__ 2 -// AARCH64-MSVC: #define __INT_MAX__ 2147483647 -// AARCH64-MSVC: #define __LDBL_DECIMAL_DIG__ 17 -// AARCH64-MSVC: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L -// AARCH64-MSVC: #define __LDBL_DIG__ 15 -// AARCH64-MSVC: #define __LDBL_EPSILON__ 2.2204460492503131e-16L -// AARCH64-MSVC: #define __LDBL_HAS_DENORM__ 1 -// AARCH64-MSVC: #define __LDBL_HAS_INFINITY__ 1 -// AARCH64-MSVC: #define __LDBL_HAS_QUIET_NAN__ 1 -// AARCH64-MSVC: #define __LDBL_MANT_DIG__ 53 -// AARCH64-MSVC: #define __LDBL_MAX_10_EXP__ 308 -// AARCH64-MSVC: #define __LDBL_MAX_EXP__ 1024 -// AARCH64-MSVC: #define __LDBL_MAX__ 1.7976931348623157e+308L -// AARCH64-MSVC: #define __LDBL_MIN_10_EXP__ (-307) -// AARCH64-MSVC: #define __LDBL_MIN_EXP__ (-1021) -// AARCH64-MSVC: #define __LDBL_MIN__ 2.2250738585072014e-308L -// AARCH64-MSVC: #define __LITTLE_ENDIAN__ 1 -// AARCH64-MSVC: #define __LONG_LONG_MAX__ 9223372036854775807LL -// AARCH64-MSVC: #define __LONG_MAX__ 2147483647L -// AARCH64-MSVC-NOT: #define __LP64__ 1 -// AARCH64-MSVC: #define __NO_INLINE__ 1 -// AARCH64-MSVC: #define __OBJC_BOOL_IS_BOOL 0 -// AARCH64-MSVC: #define __ORDER_BIG_ENDIAN__ 4321 -// AARCH64-MSVC: #define __ORDER_LITTLE_ENDIAN__ 1234 -// AARCH64-MSVC: #define __ORDER_PDP_ENDIAN__ 3412 -// AARCH64-MSVC: #define __POINTER_WIDTH__ 64 -// AARCH64-MSVC: #define __PRAGMA_REDEFINE_EXTNAME 1 -// AARCH64-MSVC: #define __SCHAR_MAX__ 127 -// AARCH64-MSVC: #define __SHRT_MAX__ 32767 -// AARCH64-MSVC: #define __SIG_ATOMIC_MAX__ 2147483647 -// AARCH64-MSVC: #define __SIG_ATOMIC_WIDTH__ 32 -// AARCH64-MSVC: #define __SIZEOF_DOUBLE__ 8 -// AARCH64-MSVC: #define __SIZEOF_FLOAT__ 4 -// AARCH64-MSVC: #define __SIZEOF_INT128__ 16 -// AARCH64-MSVC: #define __SIZEOF_INT__ 4 -// AARCH64-MSVC: #define __SIZEOF_LONG_DOUBLE__ 8 -// AARCH64-MSVC: #define __SIZEOF_LONG_LONG__ 8 -// AARCH64-MSVC: #define __SIZEOF_LONG__ 4 -// AARCH64-MSVC: #define __SIZEOF_POINTER__ 8 -// AARCH64-MSVC: #define __SIZEOF_PTRDIFF_T__ 8 -// AARCH64-MSVC: #define __SIZEOF_SHORT__ 2 -// AARCH64-MSVC: #define __SIZEOF_SIZE_T__ 8 -// AARCH64-MSVC: #define __SIZEOF_WCHAR_T__ 2 -// AARCH64-MSVC: #define __SIZEOF_WINT_T__ 2 -// AARCH64-MSVC: #define __SIZE_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __SIZE_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __SIZE_WIDTH__ 64 -// AARCH64-MSVC: #define __STDC_HOSTED__ 0 -// AARCH64-MSVC: #define __STDC_UTF_16__ 1 -// AARCH64-MSVC: #define __STDC_UTF_32__ 1 -// AARCH64-MSVC: #define __STDC_VERSION__ 201112L -// AARCH64-MSVC: #define __STDC__ 1 -// AARCH64-MSVC: #define __UINT16_C_SUFFIX__ -// AARCH64-MSVC: #define __UINT16_MAX__ 65535 -// AARCH64-MSVC: #define __UINT16_TYPE__ unsigned short -// AARCH64-MSVC: #define __UINT32_C_SUFFIX__ U -// AARCH64-MSVC: #define __UINT32_MAX__ 4294967295U -// AARCH64-MSVC: #define __UINT32_TYPE__ unsigned int -// AARCH64-MSVC: #define __UINT64_C_SUFFIX__ ULL -// AARCH64-MSVC: #define __UINT64_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __UINT64_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __UINT8_C_SUFFIX__ -// AARCH64-MSVC: #define __UINT8_MAX__ 255 -// AARCH64-MSVC: #define __UINT8_TYPE__ unsigned char -// AARCH64-MSVC: #define __UINTMAX_C_SUFFIX__ ULL -// AARCH64-MSVC: #define __UINTMAX_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __UINTMAX_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __UINTMAX_WIDTH__ 64 -// AARCH64-MSVC: #define __UINTPTR_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __UINTPTR_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __UINTPTR_WIDTH__ 64 -// AARCH64-MSVC: #define __UINT_FAST16_MAX__ 65535 -// AARCH64-MSVC: #define __UINT_FAST16_TYPE__ unsigned short -// AARCH64-MSVC: #define __UINT_FAST32_MAX__ 4294967295U -// AARCH64-MSVC: #define __UINT_FAST32_TYPE__ unsigned int -// AARCH64-MSVC: #define __UINT_FAST64_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __UINT_FAST64_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __UINT_FAST8_MAX__ 255 -// AARCH64-MSVC: #define __UINT_FAST8_TYPE__ unsigned char -// AARCH64-MSVC: #define __UINT_LEAST16_MAX__ 65535 -// AARCH64-MSVC: #define __UINT_LEAST16_TYPE__ unsigned short -// AARCH64-MSVC: #define __UINT_LEAST32_MAX__ 4294967295U -// AARCH64-MSVC: #define __UINT_LEAST32_TYPE__ unsigned int -// AARCH64-MSVC: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL -// AARCH64-MSVC: #define __UINT_LEAST64_TYPE__ long long unsigned int -// AARCH64-MSVC: #define __UINT_LEAST8_MAX__ 255 -// AARCH64-MSVC: #define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-MSVC: #define __USER_LABEL_PREFIX__ -// AARCH64-MSVC: #define __WCHAR_MAX__ 65535 -// AARCH64-MSVC: #define __WCHAR_TYPE__ unsigned short -// AARCH64-MSVC: #define __WCHAR_UNSIGNED__ 1 -// AARCH64-MSVC: #define __WCHAR_WIDTH__ 16 -// AARCH64-MSVC: #define __WINT_TYPE__ unsigned short -// AARCH64-MSVC: #define __WINT_WIDTH__ 16 -// AARCH64-MSVC: #define __aarch64__ 1 - // RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM %s // RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM -check-prefix ARM-CXX %s // @@ -7522,7 +6198,7 @@ // X86_64:#define __WINT_WIDTH__ 32 // X86_64:#define __amd64 1 // X86_64:#define __amd64__ 1 -// X86_64:#define __code_model_small_ 1 +// X86_64:#define __code_model_small__ 1 // X86_64:#define __x86_64 1 // X86_64:#define __x86_64__ 1 // @@ -7534,7 +6210,7 @@ // X86_64H:#define __x86_64h__ 1 // // RUN: %clang -xc - -E -dM -mcmodel=medium --target=i386-unknown-linux < /dev/null | FileCheck -match-full-lines -check-prefix X86_MEDIUM %s -// X86_MEDIUM:#define __code_model_medium_ 1 +// X86_MEDIUM:#define __code_model_medium__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 %s // RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 -check-prefix X32-CXX %s diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c index 6e784bfe6102d..8e7087a57991d 100644 --- a/clang/test/Sema/MicrosoftExtensions.c +++ b/clang/test/Sema/MicrosoftExtensions.c @@ -99,7 +99,7 @@ void pointer_to_integral_type_conv(char* ptr) { sh = (short)ptr; // expected-warning{{cast to smaller integer type 'short' from 'char *' is a Microsoft extension}} // This is valid ISO C. - _Bool b = (_Bool)ptr; // expected-warning{{cast to smaller integer type '_Bool' from 'char *' is a Microsoft extension}} + _Bool b = (_Bool)ptr; } typedef struct { diff --git a/clang/test/Sema/alloc-align-attr.c b/clang/test/Sema/alloc-align-attr.c index aa0fbd2cee3db..942ec117ee202 100644 --- a/clang/test/Sema/alloc-align-attr.c +++ b/clang/test/Sema/alloc-align-attr.c @@ -24,7 +24,7 @@ void *align16() { return test_ptr_alloc_align(16); } void *align15() { - return test_ptr_alloc_align(15); // expected-error {{requested alignment is not a power of 2}} + return test_ptr_alloc_align(15); // expected-warning {{requested alignment is not a power of 2}} } void *align536870912() { return test_ptr_alloc_align(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}} diff --git a/clang/test/Sema/asm-goto.cpp b/clang/test/Sema/asm-goto.cpp index d85730974359c..64addd9d75b6e 100644 --- a/clang/test/Sema/asm-goto.cpp +++ b/clang/test/Sema/asm-goto.cpp @@ -1,38 +1,38 @@ // RUN: %clang_cc1 %s -triple i386-pc-linux-gnu -verify -fsyntax-only // RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -verify -fsyntax-only -struct NonTrivial { - ~NonTrivial(); +struct S { + ~S(); int f(int); private: int k; }; -void JumpDiagnostics(int n) { +void test1(int n) { // expected-error@+1 {{cannot jump from this goto statement to its label}} goto DirectJump; // expected-note@+1 {{jump bypasses variable with a non-trivial destructor}} - NonTrivial tnp1; + S s1; DirectJump: // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} asm goto("jmp %l0;" ::::Later); // expected-note@+1 {{jump bypasses variable with a non-trivial destructor}} - NonTrivial tnp2; + S s2; // expected-note@+1 {{possible target of asm goto statement}} Later: return; } -struct S { ~S(); }; -void foo(int a) { +struct T { ~T(); }; +void test2(int a) { if (a) { FOO: // expected-note@+2 {{jump exits scope of variable with non-trivial destructor}} // expected-note@+1 {{jump exits scope of variable with non-trivial destructor}} - S s; + T t; void *p = &&BAR; // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} - asm goto("jmp %l0;" ::::BAR); + asm goto("jmp %l0;" ::::BAR); // expected-error@+1 {{cannot jump from this indirect goto statement to one of its possible targets}} goto *p; p = &&FOO; @@ -45,9 +45,7 @@ void foo(int a) { return; } - -//Asm goto: -int test16(int n) +int test3(int n) { // expected-error@+2 {{cannot jump from this asm goto statement to one of its possible targets}} // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} diff --git a/clang/test/Sema/block-call.c b/clang/test/Sema/block-call.c index 2aa1422dd9156..8dd5bd8f21b35 100644 --- a/clang/test/Sema/block-call.c +++ b/clang/test/Sema/block-call.c @@ -33,7 +33,7 @@ int main() { int (^IPCC6) (int, char (^CArg) (float)) = IPCC4; // expected-error {{incompatible block pointer types initializing 'int (^)(int, char (^)(float))' with an expression of type 'int (^)(int, char (^)(double))'}} IPCC2 = 0; - IPCC2 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *(^)()' from 'int'}} + IPCC1 = 1; // expected-error {{invalid block pointer conversion assigning to 'int *const (^)()' from 'int'}} int (^x)() = 0; int (^y)() = 3; // expected-error {{invalid block pointer conversion initializing 'int (^)()' with an expression of type 'int'}} int a = 1; diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c index e4af8f57c2a11..a51446aaa1e10 100644 --- a/clang/test/Sema/block-return.c +++ b/clang/test/Sema/block-return.c @@ -79,7 +79,7 @@ static int funk(char *s) { void next(); void foo4() { int (^xx)(const char *s) = ^(char *s) { return 1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(const char *)' with an expression of type 'int (^)(char *)'}} - int (*yy)(const char *s) = funk; // expected-warning {{incompatible pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}} + int (*yy)(const char *s) = funk; // expected-warning {{incompatible function pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}} int (^nested)(char *s) = ^(char *str) { void (^nest)(void) = ^(void) { printf("%s\n", str); }; next(); return 1; }; // expected-warning{{implicitly declaring library function 'printf' with type 'int (const char *, ...)'}} \ // expected-note{{include the header or explicitly provide a declaration for 'printf'}} diff --git a/clang/test/Sema/builtin-stackaddress.c b/clang/test/Sema/builtin-stackaddress.c index 5f63bb114624f..ecdc64d899af5 100644 --- a/clang/test/Sema/builtin-stackaddress.c +++ b/clang/test/Sema/builtin-stackaddress.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s + void* a(unsigned x) { return __builtin_return_address(0); } @@ -8,9 +9,30 @@ return __builtin_return_address(x); // expected-error{{argument to '__builtin_re } void* c(unsigned x) { +// expected-error@+1 {{argument value 4294967295 is outside the valid range [0, 65535]}} +return __builtin_return_address(-1); +} + +void* d(unsigned x) { +// expected-error@+1 {{argument value 1048575 is outside the valid range [0, 65535]}} +return __builtin_return_address(0xFFFFF); +} + +void* e(unsigned x) { return __builtin_frame_address(0); } -void d(unsigned x) { -return __builtin_frame_address(x); // expected-error{{argument to '__builtin_frame_address' must be a constant integer}} +void f(unsigned x) { +// expected-error@+1 {{argument to '__builtin_frame_address' must be a constant integer}} +return __builtin_frame_address(x); +} + +void* g(unsigned x) { +// expected-error@+1 {{argument value 4294967295 is outside the valid range [0, 65535]}} +return __builtin_frame_address(-1); +} + +void* h(unsigned x) { +// expected-error@+1 {{argument value 1048575 is outside the valid range [0, 65535]}} +return __builtin_frame_address(0xFFFFF); } diff --git a/clang/test/Sema/callingconv-ms_abi.c b/clang/test/Sema/callingconv-ms_abi.c index 64c5970adf1da..311df725d81f0 100644 --- a/clang/test/Sema/callingconv-ms_abi.c +++ b/clang/test/Sema/callingconv-ms_abi.c @@ -4,6 +4,6 @@ void __attribute__((ms_abi)) foo(void); void (*pfoo)(void) = foo; void __attribute__((sysv_abi)) bar(void); -void (*pbar)(void) = bar; // expected-warning{{incompatible pointer types}} +void (*pbar)(void) = bar; // expected-warning{{incompatible function pointer types}} -void (__attribute__((sysv_abi)) *pfoo2)(void) = foo; // expected-warning{{incompatible pointer types}} +void (__attribute__((sysv_abi)) *pfoo2)(void) = foo; // expected-warning{{incompatible function pointer types}} diff --git a/clang/test/Sema/callingconv-sysv_abi.c b/clang/test/Sema/callingconv-sysv_abi.c index 015357d054f79..2dcc30c92f4f9 100644 --- a/clang/test/Sema/callingconv-sysv_abi.c +++ b/clang/test/Sema/callingconv-sysv_abi.c @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s void __attribute__((ms_abi)) foo(void); -void (*pfoo)(void) = foo; // expected-warning{{incompatible pointer types}} +void (*pfoo)(void) = foo; // expected-warning{{incompatible function pointer types}} void __attribute__((sysv_abi)) bar(void); void (*pbar)(void) = bar; -void (__attribute__((ms_abi)) *pbar2)(void) = bar; // expected-warning{{incompatible pointer types}} +void (__attribute__((ms_abi)) *pbar2)(void) = bar; // expected-warning{{incompatible function pointer types}} diff --git a/clang/test/Sema/callingconv.c b/clang/test/Sema/callingconv.c index 6273d04f21217..c2e3a61b1ee43 100644 --- a/clang/test/Sema/callingconv.c +++ b/clang/test/Sema/callingconv.c @@ -31,7 +31,7 @@ void (__attribute__((fastcall)) *pfoo)(float*) = foo; void (__attribute__((stdcall)) *pbar)(float*) = bar; -void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible pointer types}} +void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible function pointer types}} void (*pctest0)() = ctest0; diff --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c index f16064d78dd99..0c4fc7d129fc7 100644 --- a/clang/test/Sema/cast.c +++ b/clang/test/Sema/cast.c @@ -151,7 +151,7 @@ void testCDouble(CDouble v) { } void testVoidPtr(VoidPtr v) { - (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'VoidPtr' (aka 'void *')}} + (void)(Bool) v; (void) (Int) v; // expected-warning{{cast to smaller integer type 'Int' (aka 'int') from 'VoidPtr' (aka 'void *')}} (void) (Long) v; (void) (VoidPtr) v; @@ -160,12 +160,12 @@ void testVoidPtr(VoidPtr v) { // from other -Wpointer-to-int-cast warnings. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" - (void) (Bool) v; // no-warning + (void)(Int) v; // no-warning #pragma clang diagnostic pop } void testCharPtr(CharPtr v) { - (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'CharPtr' (aka 'char *')}} + (void)(Bool) v; (void) (Int) v; // expected-warning{{cast to smaller integer type 'Int' (aka 'int') from 'CharPtr' (aka 'char *')}} (void) (Long) v; (void) (VoidPtr) v; @@ -174,7 +174,7 @@ void testCharPtr(CharPtr v) { // from other -Wpointer-to-int-cast warnings. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" - (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'CharPtr' (aka 'char *')}} + (void)(Int) v; // expected-warning{{cast to smaller integer type 'Int' (aka 'int') from 'CharPtr' (aka 'char *')}} #pragma clang diagnostic pop } diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index 760c45e02f37d..4e144041acae6 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -163,12 +163,15 @@ void test17(int x) { x = sizeof(x/0); // no warning. } -// PR6501 & PR11857 +// PR6501, PR11857, and PR23564 void test18_a(int a); // expected-note 2 {{'test18_a' declared here}} void test18_b(int); // expected-note {{'test18_b' declared here}} void test18_c(int a, int b); // expected-note 2 {{'test18_c' declared here}} void test18_d(int a, ...); // expected-note {{'test18_d' declared here}} void test18_e(int a, int b, ...); // expected-note {{'test18_e' declared here}} +#define MY_EXPORT __attribute__((visibility("default"))) +MY_EXPORT void // (no "declared here" notes on this line, no "expanded from MY_EXPORT" notes either) +test18_f(int a, int b); // expected-note 2 {{'test18_f' declared here}} void test18(int b) { test18_a(b, b); // expected-error {{too many arguments to function call, expected single argument 'a', have 2}} test18_a(); // expected-error {{too few arguments to function call, single argument 'a' was not specified}} @@ -177,6 +180,8 @@ void test18(int b) { test18_c(b, b, b); // expected-error {{too many arguments to function call, expected 2, have 3}} test18_d(); // expected-error {{too few arguments to function call, at least argument 'a' must be specified}} test18_e(); // expected-error {{too few arguments to function call, expected at least 2, have 0}} + test18_f(b); // expected-error {{too few arguments to function call, expected 2, have 1}} + test18_f(b, b, b); // expected-error {{too many arguments to function call, expected 2, have 3}} } typedef int __attribute__((address_space(256))) int_AS256; diff --git a/clang/test/Sema/overloadable.c b/clang/test/Sema/overloadable.c index 61ef3fddaf32f..360f3308302e8 100644 --- a/clang/test/Sema/overloadable.c +++ b/clang/test/Sema/overloadable.c @@ -26,7 +26,7 @@ float *accept_funcptr(int (*)(int, double)) __attribute__((overloadable)); // \ void test_funcptr(int (*f1)(int, double), int (*f2)(int, float)) { float *fp = accept_funcptr(f1); - accept_funcptr(f2); // expected-error{{call to 'accept_funcptr' is ambiguous}} + accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}} } struct X { int x; float y; }; @@ -119,8 +119,8 @@ void fn_type_conversions() { void disabled(char *c) __attribute__((overloadable, enable_if(1, "The function name lies."))); // To be clear, these should all point to the last overload of 'disabled' void (*dptr1)(char *c) = &disabled; - void (*dptr2)(void *c) = &disabled; // expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type ''}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function made ineligible by enable_if}} expected-note@-3{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'char *')}} - void (*dptr3)(int *c) = &disabled; // expected-warning{{incompatible pointer types initializing 'void (*)(int *)' with an expression of type ''}} expected-note@-6{{candidate function made ineligible by enable_if}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function has type mismatch at 1st parameter (expected 'int *' but has 'char *')}} + void (*dptr2)(void *c) = &disabled; // expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type ''}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function made ineligible by enable_if}} expected-note@-3{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'char *')}} + void (*dptr3)(int *c) = &disabled; // expected-warning{{incompatible function pointer types initializing 'void (*)(int *)' with an expression of type ''}} expected-note@-6{{candidate function made ineligible by enable_if}} expected-note@-5{{candidate function made ineligible by enable_if}} expected-note@-4{{candidate function has type mismatch at 1st parameter (expected 'int *' but has 'char *')}} void *specific_disabled = &disabled; } diff --git a/clang/test/Sema/pass-object-size.c b/clang/test/Sema/pass-object-size.c index 445d20ba6f610..8c357b2637c69 100644 --- a/clang/test/Sema/pass-object-size.c +++ b/clang/test/Sema/pass-object-size.c @@ -44,8 +44,8 @@ void FunctionPtrs() { void (*p)(void *) = NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} void (*p2)(void *) = &NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}} - void (*p3)(void *) = IsOverloaded; //expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type ''}} - void (*p4)(void *) = &IsOverloaded; //expected-warning{{incompatible pointer types initializing 'void (*)(void *)' with an expression of type ''}} + void (*p3)(void *) = IsOverloaded; //expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type ''}} + void (*p4)(void *) = &IsOverloaded; //expected-warning{{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type ''}} void (*p5)(char *) = IsOverloaded; void (*p6)(char *) = &IsOverloaded; diff --git a/clang/test/Sema/preserve-call-conv.c b/clang/test/Sema/preserve-call-conv.c index 6add3095c667f..6cd8e08cc6dc3 100644 --- a/clang/test/Sema/preserve-call-conv.c +++ b/clang/test/Sema/preserve-call-conv.c @@ -14,8 +14,8 @@ void __attribute__((preserve_most(1))) foo1(void *ptr) { // expected-error {{'pr void (__attribute__((preserve_most)) *pfoo1)(void *) = foo; -void (__attribute__((cdecl)) *pfoo2)(void *) = foo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_most))'}} -void (*pfoo3)(void *) = foo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_most))'}} +void (__attribute__((cdecl)) *pfoo2)(void *) = foo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_most))'}} +void (*pfoo3)(void *) = foo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_most))'}} typedef_fun_t typedef_fun_foo; // expected-note {{previous declaration is here}} void __attribute__((preserve_most)) typedef_fun_foo(int x) { } // expected-error {{function declared 'preserve_most' here was previously declared without calling convention}} @@ -30,8 +30,8 @@ void __attribute__((preserve_all(1))) boo1(void *ptr) { // expected-error {{'pre void (__attribute__((preserve_all)) *pboo1)(void *) = boo; -void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_all))'}} -void (*pboo3)(void *) = boo; // expected-warning {{incompatible pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_all))'}} +void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_all))'}} +void (*pboo3)(void *) = boo; // expected-warning {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_all))'}} typedef_fun_t typedef_fun_boo; // expected-note {{previous declaration is here}} void __attribute__((preserve_all)) typedef_fun_boo(int x) { } // expected-error {{function declared 'preserve_all' here was previously declared without calling convention}} diff --git a/clang/test/Sema/warn-documentation-tag-typedef.cpp b/clang/test/Sema/warn-documentation-tag-typedef.cpp new file mode 100644 index 0000000000000..0954d6a9f48da --- /dev/null +++ b/clang/test/Sema/warn-documentation-tag-typedef.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -Wdocumentation -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s + +/*! +@class Foo +*/ +typedef class { } Foo; +// CHECK-NOT: warning: + +/*! +@struct Bar +*/ +typedef struct { } Bar; +// CHECK-NOT: warning: diff --git a/clang/test/SemaCUDA/bad-calls-on-same-line.cu b/clang/test/SemaCUDA/bad-calls-on-same-line.cu index 941452470dc7a..67923323a94fa 100644 --- a/clang/test/SemaCUDA/bad-calls-on-same-line.cu +++ b/clang/test/SemaCUDA/bad-calls-on-same-line.cu @@ -33,8 +33,8 @@ inline __host__ __device__ void hd() { void host_fn() { hd(); - hd(); + hd(); // expected-note {{function template specialization 'hd'}} // expected-note@-1 {{called by 'host_fn'}} - hd(); + hd(); // expected-note {{function template specialization 'hd'}} // expected-note@-1 {{called by 'host_fn'}} } diff --git a/clang/test/SemaCUDA/call-device-fn-from-host.cu b/clang/test/SemaCUDA/call-device-fn-from-host.cu index 4d66fccd84d53..5d506d65ea58c 100644 --- a/clang/test/SemaCUDA/call-device-fn-from-host.cu +++ b/clang/test/SemaCUDA/call-device-fn-from-host.cu @@ -1,7 +1,7 @@ // RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \ // RUN: -verify -verify-ignore-unexpected=note // RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \ -// RUN: -verify=expected,omp -verify-ignore-unexpected=note -fopenmp +// RUN: -verify -verify-ignore-unexpected=note -fopenmp // Note: This test won't work with -fsyntax-only, because some of these errors // are emitted during codegen. @@ -39,7 +39,7 @@ __host__ __device__ void T::hd3() { } template __host__ __device__ void hd2() { device_fn(); } -// expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}} +// expected-error@-1 2 {{reference to __device__ function 'device_fn' in __host__ __device__ function}} void host_fn() { hd2(); } __host__ __device__ void hd() { device_fn(); } diff --git a/clang/test/SemaCUDA/call-host-fn-from-device.cu b/clang/test/SemaCUDA/call-host-fn-from-device.cu index acdd291b66457..c5bbd63d8e06c 100644 --- a/clang/test/SemaCUDA/call-host-fn-from-device.cu +++ b/clang/test/SemaCUDA/call-host-fn-from-device.cu @@ -56,14 +56,14 @@ __host__ __device__ void T::hd3() { } template __host__ __device__ void hd2() { host_fn(); } -// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}} +// expected-error@-1 2 {{reference to __host__ function 'host_fn' in __host__ __device__ function}} __global__ void kernel() { hd2(); } __host__ __device__ void hd() { host_fn(); } // expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}} template __host__ __device__ void hd3() { host_fn(); } -// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}} +// expected-error@-1 2 {{reference to __host__ function 'host_fn' in __host__ __device__ function}} __device__ void device_fn() { hd3(); } // No error because this is never instantiated. diff --git a/clang/test/SemaCUDA/openmp-target.cu b/clang/test/SemaCUDA/openmp-target.cu index c32aed44fb624..2775dc1e2c5b8 100644 --- a/clang/test/SemaCUDA/openmp-target.cu +++ b/clang/test/SemaCUDA/openmp-target.cu @@ -16,9 +16,9 @@ void bazz() {} void bazzz() {bazz();} #pragma omp declare target to(bazzz) device_type(nohost) void any() {bazz();} // expected-error {{function with 'device_type(nohost)' is not available on host}} -void host1() {bazz();} // expected-error {{function with 'device_type(nohost)' is not available on host}} +void host1() {bazz();} #pragma omp declare target to(host1) device_type(host) -void host2() {bazz();} // expected-error {{function with 'device_type(nohost)' is not available on host}} +void host2() {bazz();} #pragma omp declare target to(host2) void device() {host1();} #pragma omp declare target to(device) device_type(nohost) diff --git a/clang/test/SemaCUDA/trace-through-global.cu b/clang/test/SemaCUDA/trace-through-global.cu index 0555afea02803..f73570fa66458 100644 --- a/clang/test/SemaCUDA/trace-through-global.cu +++ b/clang/test/SemaCUDA/trace-through-global.cu @@ -38,7 +38,7 @@ void launch_kernel() { // Notice that these two diagnostics are different: Because the call to hd1 // is not dependent on T, the call to hd1 comes from 'launch_kernel', while // the call to hd3, being dependent, comes from 'launch_kernel'. - hd1(); // expected-note {{called by 'launch_kernel'}} + hd1(); // expected-note {{called by 'launch_kernel'}} hd3(T()); // expected-note {{called by 'launch_kernel'}} } diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp index 6b6734bae17d2..dd1c3462c8c1f 100644 --- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -182,19 +182,19 @@ namespace test1 { void parameter_number() { void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}} void (*ptr2)(int, int); - ptr2 = &fun; // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}} + ptr2 = &fun; // expected-error {{incompatible function pointer types assigning to 'void (*)(int, int)' from 'void (*)(int)'}} } void parameter_mismatch() { void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} void (*ptr2)(double); - ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} + ptr2 = &fun; // expected-error {{incompatible function pointer types assigning to 'void (*)(double)' from 'void (*)(int)'}} } void return_type_test() { int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}} int (*ptr2)(int); - ptr2 = &fun; // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}} + ptr2 = &fun; // expected-error {{incompatible function pointer types assigning to 'int (*)(int)' from 'void (*)(int)'}} } int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} diff --git a/clang/test/SemaCXX/alloc-align-attr.cpp b/clang/test/SemaCXX/alloc-align-attr.cpp index f910cbcf2c907..bb59ab332dee9 100644 --- a/clang/test/SemaCXX/alloc-align-attr.cpp +++ b/clang/test/SemaCXX/alloc-align-attr.cpp @@ -30,14 +30,14 @@ void dependent_impl(int align) { dependent_ret b; b.Foo(1); b.Foo2(1); - b.Foo(3); // expected-error {{requested alignment is not a power of 2}} - b.Foo2(3); // expected-error {{requested alignment is not a power of 2}} + b.Foo(3); // expected-warning {{requested alignment is not a power of 2}} + b.Foo2(3); // expected-warning {{requested alignment is not a power of 2}} b.Foo(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}} b.Foo2(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}} b.Foo(align); b.Foo2(align); - dependent_param_struct c; + dependent_param_struct c; c.Foo(1); dependent_param_struct d; // expected-note {{in instantiation of template class 'dependent_param_struct' requested here}} d.Foo(1.0); diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 9012f377e1bc2..01d2a7f58d481 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1047,6 +1047,11 @@ namespace memory_leaks { static_assert(h({new bool(true)})); // ok } +void *operator new(std::size_t, void*); +namespace std { + template constexpr T *construct(T *p) { return new (p) T; } +} + namespace dtor_call { struct A { int n; }; constexpr void f() { // expected-error {{never produces a constant expression}} @@ -1065,15 +1070,22 @@ namespace dtor_call { } static_assert((g(), true)); - constexpr bool pseudo() { + constexpr bool pseudo(bool read, bool recreate) { using T = bool; - bool b = false; - // This does evaluate the store to 'b'... + bool b = false; // expected-note {{lifetime has already ended}} + // This evaluates the store to 'b'... (b = true).~T(); - // ... but does not end the lifetime of the object. - return b; - } - static_assert(pseudo()); + // ... and ends the lifetime of the object. + return (read + ? b // expected-note {{read of object outside its lifetime}} + : true) + + (recreate + ? (std::construct(&b), true) + : true); + } + static_assert(pseudo(false, false)); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(pseudo(true, false)); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(pseudo(false, true)); constexpr void use_after_destroy() { A a; @@ -1248,6 +1260,8 @@ namespace dtor_call { // We used to think this was an -> member access because its left-hand side // is a pointer. Ensure we don't crash. p.~T(); + // Put a T back so we can destroy it again. + std::construct(&p); } static_assert((destroy_pointer(), true)); } @@ -1279,3 +1293,56 @@ namespace value_dependent_init { A a = T(); } } + +namespace mutable_subobjects { + struct A { + int m; + mutable int n; // expected-note 2{{here}} + constexpr int f() const { return m; } + constexpr int g() const { return n; } // expected-note {{mutable}} + }; + + constexpr A a = {1, 2}; + static_assert(a.f() == 1); // OK (PR44958) + static_assert(a.g() == 2); // expected-error {{constant}} expected-note {{in call}} + + constexpr A b = a; // expected-error {{constant}} expected-note {{read of mutable member 'n'}} expected-note {{in call}} + + auto &ti1 = typeid(a); + auto &ti2 = typeid(a.m); + auto &ti3 = typeid(a.n); + + constexpr void destroy1() { // expected-error {{constexpr}} + a.~A(); // expected-note {{cannot modify an object that is visible outside}} + } + using T = int; + constexpr void destroy2() { // expected-error {{constexpr}} + a.m.~T(); // expected-note {{cannot modify an object that is visible outside}} + } + constexpr void destroy3() { // expected-error {{constexpr}} + a.n.~T(); // expected-note {{cannot modify an object that is visible outside}} + } + + struct X { + mutable int n = 0; + virtual constexpr ~X() {} + }; + struct Y : X { + }; + constexpr Y y; + constexpr const X *p = &y; + constexpr const Y *q = dynamic_cast(p); + + // FIXME: It's unclear whether this should be accepted. The dynamic_cast is + // undefined after 'z.y.~Y()`, for example. We essentially assume that all + // objects that the evaluator can reach have unbounded lifetimes. (We make + // the same assumption when evaluating member function calls.) + struct Z { + mutable Y y; + }; + constexpr Z z; + constexpr const X *pz = &z.y; + constexpr const Y *qz = dynamic_cast(pz); + auto &zti = typeid(z.y); + static_assert(&zti == &typeid(Y)); +} diff --git a/clang/test/SemaCXX/cstyle-cast.cpp b/clang/test/SemaCXX/cstyle-cast.cpp index 2327d7b51d97c..32a6e205f769d 100644 --- a/clang/test/SemaCXX/cstyle-cast.cpp +++ b/clang/test/SemaCXX/cstyle-cast.cpp @@ -178,6 +178,11 @@ void integral_conversion() fnptr fnp = (fnptr)(l); (void)(char)(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} (void)(long)(fnp); + + (void)(bool)((void*)0); + (void)(bool)((int*)0); + (void)(char)((void*)0); // expected-error {{cast from pointer to smaller type 'char' loses information}} + (void)(char)((int*)0); // expected-error {{cast from pointer to smaller type 'char' loses information}} } void pointer_conversion() diff --git a/clang/test/SemaCXX/cxx17-compat.cpp b/clang/test/SemaCXX/cxx17-compat.cpp index e063b1fc18073..b65ed3ea340b7 100644 --- a/clang/test/SemaCXX/cxx17-compat.cpp +++ b/clang/test/SemaCXX/cxx17-compat.cpp @@ -1,30 +1,30 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++17 -pedantic -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++2a -Wc++17-compat-pedantic -verify %s -Wno-defaulted-function-deleted +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -Wc++17-compat-pedantic -verify %s -Wno-defaulted-function-deleted struct A {}; int (A::*pa)() const&; int use_pa = (A().*pa)(); #if __cplusplus <= 201703L - // expected-warning@-2 {{invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension}} + // expected-warning@-2 {{invoking a pointer to a 'const &' member function on an rvalue is a C++20 extension}} #else - // expected-warning@-4 {{invoking a pointer to a 'const &' member function on an rvalue is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{invoking a pointer to a 'const &' member function on an rvalue is incompatible with C++ standards before C++20}} #endif struct B { void b() { (void) [=, this] {}; #if __cplusplus <= 201703L - // expected-warning@-2 {{explicit capture of 'this' with a capture default of '=' is a C++2a extension}} + // expected-warning@-2 {{explicit capture of 'this' with a capture default of '=' is a C++20 extension}} #else - // expected-warning@-4 {{explicit capture of 'this' with a capture default of '=' is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{explicit capture of 'this' with a capture default of '=' is incompatible with C++ standards before C++20}} #endif } int n : 5 = 0; #if __cplusplus <= 201703L - // expected-warning@-2 {{default member initializer for bit-field is a C++2a extension}} + // expected-warning@-2 {{default member initializer for bit-field is a C++20 extension}} #else - // expected-warning@-4 {{default member initializer for bit-field is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{default member initializer for bit-field is incompatible with C++ standards before C++20}} #endif }; @@ -33,14 +33,14 @@ decltype(Lambda) AnotherLambda; #if __cplusplus <= 201703L // expected-error@-2 {{no matching constructor}} expected-note@-3 2{{candidate}} #else - // expected-warning@-4 {{default construction of lambda is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{default construction of lambda is incompatible with C++ standards before C++20}} #endif void copy_lambda() { Lambda = Lambda; } #if __cplusplus <= 201703L // expected-error@-2 {{deleted}} expected-note@-10 {{lambda}} #else - // expected-warning@-4 {{assignment of lambda is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{assignment of lambda is incompatible with C++ standards before C++20}} #endif struct DefaultDeleteWrongTypeBase { @@ -51,16 +51,16 @@ struct DefaultDeleteWrongType : DefaultDeleteWrongTypeBase { #if __cplusplus <= 201703L // expected-error@-2 {{a member or base requires it to be non-const}} #else - // expected-warning@-4 {{explicitly defaulting this copy constructor with a type different from the implicit type is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{explicitly defaulting this copy constructor with a type different from the implicit type is incompatible with C++ standards before C++20}} #endif }; void ForRangeInit() { for (int arr[3] = {1, 2, 3}; int n : arr) {} #if __cplusplus <= 201703L - // expected-warning@-2 {{range-based for loop initialization statements are a C++2a extension}} + // expected-warning@-2 {{range-based for loop initialization statements are a C++20 extension}} #else - // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++20}} #endif } @@ -69,23 +69,23 @@ struct ConstexprVirtual { #if __cplusplus <= 201703L // expected-error@-2 {{virtual function cannot be constexpr}} #else - // expected-warning@-4 {{virtual constexpr functions are incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{virtual constexpr functions are incompatible with C++ standards before C++20}} #endif }; struct C { int x, y, z; }; static auto [cx, cy, cz] = C(); #if __cplusplus <= 201703L - // expected-warning@-2 {{decomposition declaration declared 'static' is a C++2a extension}} + // expected-warning@-2 {{decomposition declaration declared 'static' is a C++20 extension}} #else - // expected-warning@-4 {{decomposition declaration declared 'static' is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{decomposition declaration declared 'static' is incompatible with C++ standards before C++20}} #endif void f() { static thread_local auto [cx, cy, cz] = C(); #if __cplusplus <= 201703L - // expected-warning@-2 {{decomposition declaration declared with 'static thread_local' specifiers is a C++2a extension}} + // expected-warning@-2 {{decomposition declaration declared with 'static thread_local' specifiers is a C++20 extension}} #else - // expected-warning@-4 {{decomposition declaration declared with 'static thread_local' specifiers is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{decomposition declaration declared with 'static thread_local' specifiers is incompatible with C++ standards before C++20}} #endif } @@ -103,7 +103,7 @@ struct DefaultedComparisons { #if __cplusplus <= 201703L // expected-error@-2 {{'operator<=' cannot be the name of a variable or data member}} expected-error@-2 0+{{}} expected-warning@-2 {{}} #else - // expected-warning@-4 {{'<=>' operator is incompatible with C++ standards before C++2a}} + // expected-warning@-4 {{'<=>' operator is incompatible with C++ standards before C++20}} #endif bool operator<(const DefaultedComparisons&) const = default; bool operator<=(const DefaultedComparisons&) const = default; diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp index 2e0bbaa31c78e..d7ebfdc3133a4 100644 --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s -fcxx-exceptions -// RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks %s -fcxx-exceptions +// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -fblocks %s -fcxx-exceptions // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -fcxx-exceptions // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER -fcxx-exceptions @@ -25,7 +25,7 @@ namespace ns1 { namespace ns2 { auto L = [](int I) constexpr { if (I == 5) asm("non-constexpr"); }; #if __cpp_constexpr < 201907L - //expected-warning@-2{{use of this statement in a constexpr function is a C++2a extension}} + //expected-warning@-2{{use of this statement in a constexpr function is a C++20 extension}} #endif } // end ns1 diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp index d2dc939beb5df..336c103ef0a4a 100644 --- a/clang/test/SemaCXX/cxx1z-decomposition.cpp +++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++17 -verify %s void use_from_own_init() { auto [a] = a; // expected-error {{binding 'a' cannot appear in the initializer of its own decomposition declaration}} @@ -83,7 +83,7 @@ template void dependent_foreach(T t) { struct PR37352 { int n; - void f() { static auto [a] = *this; } // expected-warning {{C++2a extension}} + void f() { static auto [a] = *this; } // expected-warning {{C++20 extension}} }; namespace instantiate_template { diff --git a/clang/test/SemaCXX/cxx2a-compat.cpp b/clang/test/SemaCXX/cxx2a-compat.cpp index c8d22b731076e..de9d4442a45eb 100644 --- a/clang/test/SemaCXX/cxx2a-compat.cpp +++ b/clang/test/SemaCXX/cxx2a-compat.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++2a-compat-pedantic -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++2a -pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++20-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -pedantic -verify %s struct A { // expected-note 0+{{candidate}} A() = default; // expected-note 0+{{candidate}} @@ -7,7 +7,7 @@ struct A { // expected-note 0+{{candidate}} }; A a1 = {1, 2}; #if __cplusplus <= 201703L - // expected-warning@-2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} + // expected-warning@-2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++20}} #else // expected-error@-4 {{no matching constructor}} #endif @@ -17,7 +17,7 @@ struct B : A { A a; }; B b1 = {{}, {}}; // ok B b2 = {1, 2, 3, 4}; #if __cplusplus <= 201703L - // expected-warning@-2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} + // expected-warning@-2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++20}} #else // expected-error@-4 2{{no viable conversion from 'int' to 'A'}} #endif @@ -43,7 +43,7 @@ struct C { explicit(C)(int); }; #if __cplusplus <= 201703L -// expected-warning@-3 {{this expression will be parsed as explicit(bool) in C++2a}} +// expected-warning@-3 {{this expression will be parsed as explicit(bool) in C++20}} #if defined(__cpp_conditional_explicit) #error "the feature test macro __cpp_conditional_explicit isn't correct" #endif @@ -61,8 +61,8 @@ struct C { auto l = []() consteval {}; int consteval(); #if __cplusplus <= 201703L -// expected-warning@-3 {{'consteval' is a keyword in C++2a}} +// expected-warning@-3 {{'consteval' is a keyword in C++20}} // expected-error@-4 {{expected body of lambda expression}} #else // expected-error@-5 {{expected unqualified-id}} -#endif \ No newline at end of file +#endif diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp index 7dc2500dbbfb2..653fcf439c156 100644 --- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++2a %s -verify=cxx20,expected,pedantic,override,reorder -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify=expected,pedantic,override,reorder -Wno-c++2a-designator -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify=cxx20,expected,pedantic -Werror=c99-designator -Wno-reorder-init-list -Wno-initializer-overrides -// RUN: %clang_cc1 -std=c++2a %s -verify=cxx20,expected,reorder -Wno-c99-designator -Werror=reorder-init-list -Wno-initializer-overrides -// RUN: %clang_cc1 -std=c++2a %s -verify=cxx20,expected,override -Wno-c99-designator -Wno-reorder-init-list -Werror=initializer-overrides -// RUN: %clang_cc1 -std=c++2a %s -verify=cxx20,expected -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,pedantic,override,reorder -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,pedantic,override,reorder -Wno-c++20-designator -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,pedantic -Werror=c99-designator -Wno-reorder-init-list -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,reorder -Wno-c99-designator -Werror=reorder-init-list -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,override -Wno-c99-designator -Wno-reorder-init-list -Werror=initializer-overrides +// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides namespace class_with_ctor { diff --git a/clang/test/SemaCXX/decl-microsoft-call-conv.cpp b/clang/test/SemaCXX/decl-microsoft-call-conv.cpp index a2a04ac9c8b99..b399d8e35bd4f 100644 --- a/clang/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/clang/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -239,7 +239,7 @@ namespace test8 { template struct S { void f(T t) { // expected-note {{previous declaration is here}} - t = 42; // expected-error {{assigning to 'void *' from incompatible type 'int'}} + t = 42; // expected-error {{incompatible integer to pointer conversion assigning to 'void *' from 'int'}} } }; template<> void __cdecl S::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} diff --git a/clang/test/SemaCXX/goto.cpp b/clang/test/SemaCXX/goto.cpp index 2d37ea9099a28..beaf88cf60f10 100644 --- a/clang/test/SemaCXX/goto.cpp +++ b/clang/test/SemaCXX/goto.cpp @@ -40,7 +40,7 @@ namespace N { } void g() { - end = 1; // expected-error{{assigning to 'double *' from incompatible type 'int'}} + end = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'double *' from 'int'}} } void h(int end) { diff --git a/clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp b/clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp index 5782a6dbaeae0..68eae7f69c783 100644 --- a/clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp +++ b/clang/test/SemaCXX/int-ptr-cast-SFINAE.cpp @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17 void foo(int* a, int *b) { - a -= b; // expected-warning {{incompatible integer to pointer conversion assigning to 'int *' from}} + a -= b; // expected-error {{incompatible integer to pointer conversion assigning to 'int *' from}} } template T declval(); diff --git a/clang/test/SemaCXX/member-init.cpp b/clang/test/SemaCXX/member-init.cpp index f2c06446265b8..ff5dadea16e62 100644 --- a/clang/test/SemaCXX/member-init.cpp +++ b/clang/test/SemaCXX/member-init.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s struct Bitfield { - int n : 3 = 7; // expected-warning {{C++2a extension}} expected-warning {{changes value from 7 to -1}} + int n : 3 = 7; // expected-warning {{C++20 extension}} expected-warning {{changes value from 7 to -1}} }; int a; diff --git a/clang/test/SemaCXX/ms-property-error.cpp b/clang/test/SemaCXX/ms-property-error.cpp index ca52538f3a670..4173f840960c7 100644 --- a/clang/test/SemaCXX/ms-property-error.cpp +++ b/clang/test/SemaCXX/ms-property-error.cpp @@ -19,7 +19,7 @@ class St { x[2][3] = 4; ++x[2][3]; x[1][2] = x[3][4][5]; // expected-error {{too many arguments to function call, expected 2, have 3}} - ptr = x[1][2] = x[3][4]; // expected-error {{assigning to 'char *' from incompatible type 'int'}} + ptr = x[1][2] = x[3][4]; // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} } }; diff --git a/clang/test/SemaObjC/arc.m b/clang/test/SemaObjC/arc.m index 639483913fa56..e46d66b0dcf32 100644 --- a/clang/test/SemaObjC/arc.m +++ b/clang/test/SemaObjC/arc.m @@ -114,7 +114,8 @@ void test5() { __autoreleasing id *a = &x; // expected-error {{initializing '__autoreleasing id *' with an expression of type '__strong id *' changes retain/release properties of pointer}} - a = &x; // expected-error {{assigning '__strong id *' to '__autoreleasing id *' changes retain/release properties of pointer}} + __autoreleasing id *aa; + aa = &x; // expected-error {{assigning '__strong id *' to '__autoreleasing id *' changes retain/release properties of pointer}} extern void test5_helper2(id const *); test5_helper2(&x); diff --git a/clang/test/SemaObjC/comptypes-legal.m b/clang/test/SemaObjC/comptypes-legal.m index 7ac4e143338a3..57b040c613219 100644 --- a/clang/test/SemaObjC/comptypes-legal.m +++ b/clang/test/SemaObjC/comptypes-legal.m @@ -33,7 +33,7 @@ void foo(void) { // GCC currently allows this (it has some fiarly new support for covariant return types and contravariant argument types). // Since registerFunc: expects a Derived object as it's second argument, I don't know why this would be legal. - [Derived registerFunc: ExternFunc]; // expected-warning{{incompatible pointer types sending 'NSObject *(NSObject *, NSObject *)' to parameter of type 'FuncSignature *'}} + [Derived registerFunc: ExternFunc]; // expected-warning{{incompatible function pointer types sending 'NSObject *(NSObject *, NSObject *)' to parameter of type 'FuncSignature *' (aka 'id (*)(NSObject *, Derived *)')}} } // rdar://10751015 diff --git a/clang/test/SemaObjCXX/arc-type-conversion.mm b/clang/test/SemaObjCXX/arc-type-conversion.mm index 8544726e25ad3..1e3790bfa472b 100644 --- a/clang/test/SemaObjCXX/arc-type-conversion.mm +++ b/clang/test/SemaObjCXX/arc-type-conversion.mm @@ -124,12 +124,12 @@ void test_unsafe_unretained(__strong id *sip, __weak id *wip, __autoreleasing id *aip, __unsafe_unretained id *uip, const __unsafe_unretained id *cuip) { - uip = sip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__strong id *'}} - uip = wip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__weak id *'}} - uip = aip; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type '__autoreleasing id *'}} + uip = sip; // expected-error{{assigning '__strong id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}} + uip = wip; // expected-error{{assigning '__weak id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}} + uip = aip; // expected-error{{assigning '__autoreleasing id *' to '__unsafe_unretained id *' changes retain/release properties of pointer}} cuip = sip; - cuip = wip; // expected-error{{assigning to '__unsafe_unretained id const *' from incompatible type '__weak id *'}} + cuip = wip; // expected-error{{assigning '__weak id *' to '__unsafe_unretained id const *' changes retain/release properties of pointer}} cuip = aip; } diff --git a/clang/test/SemaObjCXX/comptypes-1.mm b/clang/test/SemaObjCXX/comptypes-1.mm index abb87775d152b..595223aa793d6 100644 --- a/clang/test/SemaObjCXX/comptypes-1.mm +++ b/clang/test/SemaObjCXX/comptypes-1.mm @@ -37,9 +37,9 @@ int main() warning, unless done from an 'id'. */ obj_c = obj; /* Ok */ obj_c = obj_p; // expected-error {{assigning to 'MyClass *' from incompatible type 'id'}} - obj_c = obj_cp; // expected-error {{assigning to 'MyClass *' from incompatible type 'MyOtherClass *'}} - obj_c = obj_C; // expected-error {{assigning to 'MyClass *' from incompatible type 'Class'}} - obj_c = obj_CP; // expected-error {{assigning to 'MyClass *' from incompatible type 'Class'}} + obj_c = obj_cp; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'MyOtherClass *'}} + obj_c = obj_C; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'Class'}} + obj_c = obj_CP; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'Class'}} /* Assigning to an 'id' variable should generate a warning if done from a 'MyClass *' (which doesn't implement @@ -48,28 +48,28 @@ int main() obj_p = obj; /* Ok */ obj_p = obj_c; // expected-error {{assigning to 'id' from incompatible type 'MyClass *'}} obj_p = obj_cp; /* Ok */ - obj_p = obj_C; // expected-error {{assigning to 'id' from incompatible type 'Class'}} + obj_p = obj_C; // expected-error {{incompatible pointer types assigning to 'id' from 'Class'}} obj_p = obj_CP; // expected-error {{assigning to 'id' from incompatible type 'Class'}} /* Assigning to a 'MyOtherClass *' variable should always generate a warning, unless done from an 'id' or an 'id' (since MyOtherClass implements MyProtocol). */ obj_cp = obj; /* Ok */ - obj_cp = obj_c; // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'MyClass *'}} + obj_cp = obj_c; // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'MyClass *'}} obj_cp = obj_p; /* Ok */ - obj_cp = obj_C; // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'Class'}} - obj_cp = obj_CP; // expected-error {{assigning to 'MyOtherClass *' from incompatible type 'Class'}} + obj_cp = obj_C; // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'Class'}} + obj_cp = obj_CP; // expected-error {{incompatible pointer types assigning to 'MyOtherClass *' from 'Class'}} obj_C = obj; // Ok - obj_C = obj_p; // expected-error {{assigning to 'Class' from incompatible type 'id'}} - obj_C = obj_c; // expected-error {{assigning to 'Class' from incompatible type 'MyClass *'}} - obj_C = obj_cp; // expected-error {{assigning to 'Class' from incompatible type 'MyOtherClass *'}} + obj_C = obj_p; // expected-error {{incompatible pointer types assigning to 'Class' from 'id'}} + obj_C = obj_c; // expected-error {{incompatible pointer types assigning to 'Class' from 'MyClass *'}} + obj_C = obj_cp; // expected-error {{incompatible pointer types assigning to 'Class' from 'MyOtherClass *'}} obj_C = obj_CP; // Ok obj_CP = obj; // Ok obj_CP = obj_p; // expected-error {{assigning to 'Class' from incompatible type 'id'}} - obj_CP = obj_c; // expected-error {{assigning to 'Class' from incompatible type 'MyClass *}} - obj_CP = obj_cp; // expected-error {{assigning to 'Class' from incompatible type 'MyOtherClass *'}} + obj_CP = obj_c; // expected-error {{incompatible pointer types assigning to 'Class' from 'MyClass *'}} + obj_CP = obj_cp; // expected-error {{incompatible pointer types assigning to 'Class' from 'MyOtherClass *'}} obj_CP = obj_C; // Ok /* Any comparison involving an 'id' must be without warnings. */ diff --git a/clang/test/SemaObjCXX/comptypes-7.mm b/clang/test/SemaObjCXX/comptypes-7.mm index 010c2cacc484e..cc3d085e1c617 100644 --- a/clang/test/SemaObjCXX/comptypes-7.mm +++ b/clang/test/SemaObjCXX/comptypes-7.mm @@ -23,27 +23,27 @@ int main() /* These should all generate errors. */ - obj = i; // expected-error {{assigning to 'id' from incompatible type 'int'}} - obj = j; // expected-error {{assigning to 'id' from incompatible type 'int *'}} + obj = i; // expected-error {{incompatible integer to pointer conversion assigning to 'id' from 'int'}} + obj = j; // expected-error {{incompatible pointer types assigning to 'id' from 'int *'}} - obj_p = i; // expected-error {{assigning to 'id' from incompatible type 'int'}} - obj_p = j; // expected-error {{assigning to 'id' from incompatible type 'int *'}} + obj_p = i; // expected-error {{incompatible integer to pointer conversion assigning to 'id' from 'int'}} + obj_p = j; // expected-error {{incompatible pointer types assigning to 'id' from 'int *'}} - obj_c = i; // expected-error {{assigning to 'MyClass *' from incompatible type 'int'}} - obj_c = j; // expected-error {{assigning to 'MyClass *' from incompatible type 'int *'}} + obj_c = i; // expected-error {{incompatible integer to pointer conversion assigning to 'MyClass *' from 'int'}} + obj_c = j; // expected-error {{incompatible pointer types assigning to 'MyClass *' from 'int *'}} - obj_C = i; // expected-error {{assigning to 'Class' from incompatible type 'int'}} - obj_C = j; // expected-error {{assigning to 'Class' from incompatible type 'int *'}} + obj_C = i; // expected-error {{incompatible integer to pointer conversion assigning to 'Class' from 'int'}} + obj_C = j; // expected-error {{incompatible pointer types assigning to 'Class' from 'int *'}} - i = obj; // expected-error {{assigning to 'int' from incompatible type 'id'}} - i = obj_p; // expected-error {{assigning to 'int' from incompatible type 'id'}} - i = obj_c; // expected-error {{assigning to 'int' from incompatible type 'MyClass *'}} - i = obj_C; // expected-error {{assigning to 'int' from incompatible type 'Class'}} + i = obj; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id'}} + i = obj_p; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id'}} + i = obj_c; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'MyClass *'}} + i = obj_C; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'Class'}} - j = obj; // expected-error {{assigning to 'int *' from incompatible type 'id'}} - j = obj_p; // expected-error {{assigning to 'int *' from incompatible type 'id'}} - j = obj_c; // expected-error {{assigning to 'int *' from incompatible type 'MyClass *'}} - j = obj_C; // expected-error {{assigning to 'int *' from incompatible type 'Class'}} + j = obj; // expected-error {{incompatible pointer types assigning to 'int *' from 'id'}} + j = obj_p; // expected-error {{incompatible pointer types assigning to 'int *' from 'id'}} + j = obj_c; // expected-error {{incompatible pointer types assigning to 'int *' from 'MyClass *'}} + j = obj_C; // expected-error {{incompatible pointer types assigning to 'int *' from 'Class'}} if (obj == i) foo() ; // expected-error {{comparison between pointer and integer ('id' and 'int')}} if (i == obj) foo() ; // expected-error {{comparison between pointer and integer ('int' and 'id')}} diff --git a/clang/test/SemaObjCXX/instantiate-expr.mm b/clang/test/SemaObjCXX/instantiate-expr.mm index e9d296db8fecc..fd674d8828cb3 100644 --- a/clang/test/SemaObjCXX/instantiate-expr.mm +++ b/clang/test/SemaObjCXX/instantiate-expr.mm @@ -18,8 +18,8 @@ @interface A { template void f(U value, V value2) { - get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} - get_an_A(N).prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}} + get_an_A(N)->ivar = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}} + get_an_A(N).prop = value2; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'double *'}} T c = get_an_id(N)->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}} \ // expected-warning 3 {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}} } @@ -33,8 +33,8 @@ void f(U value, V value2) { // ivar reference. template void f2(T ptr, U value, V value2) { - ptr->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} - ptr.prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}} + ptr->ivar = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}} + ptr.prop = value2; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'double *'}} } template void f2(A*, int, int); @@ -60,7 +60,7 @@ - (void)setFoo:(int)value; template void f4(B *b, T value) { - b.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} + b.foo = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}} } template void f4(B*, int); @@ -68,7 +68,7 @@ void f4(B *b, T value) { template void f5(T ptr, U value) { - ptr.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} + ptr.foo = value; // expected-error{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}} } template void f5(B*, int); diff --git a/clang/test/SemaObjCXX/instantiate-stmt.mm b/clang/test/SemaObjCXX/instantiate-stmt.mm index 7575f7ad1a8f0..bc870206eac4d 100644 --- a/clang/test/SemaObjCXX/instantiate-stmt.mm +++ b/clang/test/SemaObjCXX/instantiate-stmt.mm @@ -64,7 +64,7 @@ void fast_enumeration_test(T collection) { template void try_catch_finally_test(U value) { @try { - value = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}} + value = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}} } @catch (T obj) { // expected-error{{@catch parameter is not a pointer to an interface type}} id x = obj; diff --git a/clang/test/SemaObjCXX/noescape.mm b/clang/test/SemaObjCXX/noescape.mm index efa2a76d668a0..199d1ae11ee71 100644 --- a/clang/test/SemaObjCXX/noescape.mm +++ b/clang/test/SemaObjCXX/noescape.mm @@ -74,7 +74,7 @@ -(void) m0:(int*) p {} void test0() { fnptr0 = &func0; fnptr0 = &noescapeFunc2; - fnptr1 = &func0; // expected-error {{assigning to 'void (*)(__attribute__((noescape)) int *)' from incompatible type 'void (*)(int *)'}} + fnptr1 = &func0; // expected-error {{incompatible function pointer types assigning to 'void (*)(__attribute__((noescape)) int *)' from 'void (*)(int *)'}} fnptr1 = &noescapeFunc2; S4<&func0> e0; S4<&noescapeFunc2> e1; diff --git a/clang/test/SemaObjCXX/nullability-pragmas.mm b/clang/test/SemaObjCXX/nullability-pragmas.mm index 817d056a14aca..bbb8cd8832a55 100644 --- a/clang/test/SemaObjCXX/nullability-pragmas.mm +++ b/clang/test/SemaObjCXX/nullability-pragmas.mm @@ -32,26 +32,26 @@ void test_pragmas_1(A * _Nonnull a, AA * _Nonnull aa) { [a method4: a]; // expected-error{{cannot initialize a parameter of type 'NSErrorPtr _Nullable * _Nullable' (aka 'NSError **') with an lvalue of type 'A * _Nonnull'}} float *ptr; - ptr = f13(); // expected-error{{assigning to 'float *' from incompatible type 'int_ptr _Nonnull' (aka 'int *')}} - ptr = f14(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}} - ptr = [a method1:a]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}} - ptr = a.aProp; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}} - ptr = global_int_ptr; // expected-error{{assigning to 'float *' from incompatible type 'int * _Nonnull'}} - ptr = f15(); // expected-error{{assigning to 'float *' from incompatible type 'int * _Null_unspecified'}} - ptr = f16(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}} - ptr = [a method2]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}} - - ptr = aa->ivar1; // expected-error{{from incompatible type 'id'}} - ptr = aa->ivar2; // expected-error{{from incompatible type 'id _Nonnull'}} + ptr = f13(); // expected-error{{incompatible pointer types assigning to 'float *' from 'int_ptr _Nonnull' (aka 'int *')}} + ptr = f14(); // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}} + ptr = [a method1:a]; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}} + ptr = a.aProp; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Nonnull'}} + ptr = global_int_ptr; // expected-error{{incompatible pointer types assigning to 'float *' from 'int * _Nonnull'}} + ptr = f15(); // expected-error{{incompatible pointer types assigning to 'float *' from 'int * _Null_unspecified'}} + ptr = f16(); // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Null_unspecified'}} + ptr = [a method2]; // expected-error{{incompatible pointer types assigning to 'float *' from 'A * _Null_unspecified'}} + + ptr = aa->ivar1; // expected-error{{incompatible pointer types assigning to 'float *' from 'id'}} + ptr = aa->ivar2; // expected-error{{incompatible pointer types assigning to 'float *' from 'id _Nonnull'}} } void test_pragmas_generics(void) { float *fp; NSGeneric *genC; - fp = [genC tee]; // expected-error{{from incompatible type 'C *'}} - fp = [genC maybeTee]; // expected-error{{from incompatible type 'C * _Nullable'}} + fp = [genC tee]; // expected-error{{incompatible pointer types assigning to 'float *' from 'C *'}} + fp = [genC maybeTee]; // expected-error{{incompatible pointer types assigning to 'float *' from 'C * _Nullable'}} Generic_with_C genC2; - fp = genC2; // expected-error{{from incompatible type 'Generic_with_C' (aka 'NSGeneric *')}} + fp = genC2; // expected-error{{incompatible pointer types assigning to 'float *' from 'Generic_with_C' (aka 'NSGeneric *')}} } diff --git a/clang/test/SemaObjCXX/objc-container-subscripting.mm b/clang/test/SemaObjCXX/objc-container-subscripting.mm index 537e1520df5cc..a7a3263ee5118 100644 --- a/clang/test/SemaObjCXX/objc-container-subscripting.mm +++ b/clang/test/SemaObjCXX/objc-container-subscripting.mm @@ -12,7 +12,7 @@ void test_dictionary_subscripts(T base, U key, O obj) { base[key] = obj; // expected-error {{expected method to write array element not found on object of type 'NSMutableDictionary *'}} \ // expected-error {{cannot initialize a parameter of type 'id' with an lvalue of type 'int'}} obj = base[key]; // expected-error {{expected method to read array element not found on object of type 'NSMutableDictionary *'}} \ - // expected-error {{assigning to 'int' from incompatible type 'id'}} + // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'id'}} } diff --git a/clang/test/SemaObjCXX/parameterized_classes_subst.mm b/clang/test/SemaObjCXX/parameterized_classes_subst.mm index 88d001274b1ce..2eb630aeedf49 100644 --- a/clang/test/SemaObjCXX/parameterized_classes_subst.mm +++ b/clang/test/SemaObjCXX/parameterized_classes_subst.mm @@ -106,27 +106,27 @@ void test_message_send_result( NSArray *stringArray, void (^block)(void)) { int *ip; - ip = [stringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}} - ip = [mutStringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}} - ip = [widgetSet firstObject]; // expected-error{{from incompatible type 'Widget *'}} - ip = [untypedMutSet firstObject]; // expected-error{{from incompatible type 'id'}} - ip = [mutStringArraySet firstObject]; // expected-error{{from incompatible type 'NSArray *'}} - ip = [set firstObject]; // expected-error{{from incompatible type 'id'}} - ip = [mutSet firstObject]; // expected-error{{from incompatible type 'id'}} - ip = [mutArraySet firstObject]; // expected-error{{from incompatible type 'id'}} - ip = [block firstObject]; // expected-error{{from incompatible type 'id'}} - - ip = [stringSet findObject:@"blah"]; // expected-error{{from incompatible type 'NSString *'}} + ip = [stringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} + ip = [mutStringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} + ip = [widgetSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}} + ip = [untypedMutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} + ip = [mutStringArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = [set firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} + ip = [mutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} + ip = [mutArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} + ip = [block firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} + + ip = [stringSet findObject:@"blah"]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} // Class messages. - ip = [NSSet alloc]; // expected-error{{from incompatible type 'NSSet *'}} - ip = [NSSet alloc]; // expected-error{{from incompatible type 'NSSet *'}} - ip = [MutableSetOfArrays alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays *'}} - ip = [MutableSetOfArrays alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays *'}} - ip = [NSArray array]; // expected-error{{from incompatible type 'NSArray *'}} - ip = [NSArray array]; // expected-error{{from incompatible type 'NSArray *'}} + ip = [NSSet alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet *'}} + ip = [NSSet alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet *'}} + ip = [MutableSetOfArrays alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays *'}} + ip = [MutableSetOfArrays alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays *'}} + ip = [NSArray array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = [NSArray array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = [[NSMutableArray alloc] init]; // expected-error{{from incompatible type 'NSMutableArray *'}} + ip = [[NSMutableArray alloc] init]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSMutableArray *'}} [[NSMutableArray alloc] initWithArray: stringArray]; // okay [[NSMutableArray alloc] initWithArray: stringArray]; // okay @@ -166,16 +166,16 @@ void test_property_read( MutableSetOfArrays *mutArraySet, NSMutableDictionary *mutDict) { int *ip; - ip = stringSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = mutStringSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = widgetSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = untypedMutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = mutStringArraySet.allObjects; // expected-error{{from incompatible type 'NSArray *> *'}} - ip = set.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = mutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - ip = mutArraySet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} - - ip = mutDict.someRandomKey; // expected-error{{from incompatible type '__kindof id'}} + ip = stringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = mutStringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = widgetSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = untypedMutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = mutStringArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *> *'}} + ip = set.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = mutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = mutArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + + ip = mutDict.someRandomKey; // expected-error{{incompatible pointer types assigning to 'int *' from '__kindof id'}} } void test_property_write( @@ -215,27 +215,27 @@ void test_subscripting( Widget *widget; Window *window; - ip = stringArray[0]; // expected-error{{from incompatible type 'NSString *'}} + ip = stringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} - ip = mutStringArray[0]; // expected-error{{from incompatible type 'NSString *'}} + ip = mutStringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}} - ip = array[0]; // expected-error{{from incompatible type 'id'}} + ip = array[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} - ip = mutArray[0]; // expected-error{{from incompatible type 'id'}} + ip = mutArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} mutArray[0] = ip; // expected-error{{parameter of type 'id'}} - ip = stringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}} + ip = stringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}} widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}} - ip = mutStringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}} + ip = mutStringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}} widget = mutStringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}} mutStringWidgetDict[string] = ip; // expected-error{{parameter of type 'Widget *'}} mutStringWidgetDict[widget] = widget; // expected-error{{parameter of type 'NSString *'}} - ip = dict[string]; // expected-error{{from incompatible type 'id'}} + ip = dict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} - ip = mutDict[string]; // expected-error{{incompatible type 'id'}} + ip = mutDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} mutDict[string] = ip; // expected-error{{parameter of type 'id'}} widget = mutDict[window]; @@ -249,15 +249,15 @@ void test_instance_variable(NSArray *stringArray, NSArray *array) { int *ip; - ip = stringArray->data; // expected-error{{from incompatible type 'NSString **'}} - ip = array->data; // expected-error{{from incompatible type 'id *'}} + ip = stringArray->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString **'}} + ip = array->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'id *'}} } @implementation WindowArray - (void)testInstanceVariable { int *ip; - ip = data; // expected-error{{from incompatible type 'Window **'}} + ip = data; // expected-error{{incompatible pointer types assigning to 'int *' from 'Window **'}} } @end @@ -276,13 +276,13 @@ void test_implicit_conversions(NSArray *stringArray, stringArray = array; // Specialized -> specialized failure (same level). - stringArray = numberArray; // expected-error{{assigning to 'NSArray *' from incompatible type 'NSArray *'}} + stringArray = numberArray; // expected-error{{incompatible pointer types assigning to 'NSArray *' from 'NSArray *'}} // Specialized -> specialized (different levels). stringArray = mutStringArray; // Specialized -> specialized failure (different levels). - numberArray = mutStringArray; // expected-error{{assigning to 'NSArray *' from incompatible type 'NSMutableArray *'}} + numberArray = mutStringArray; // expected-error{{incompatible pointer types assigning to 'NSArray *' from 'NSMutableArray *'}} // Unspecialized -> specialized (different levels). stringArray = mutArray; @@ -334,19 +334,19 @@ void test_ternary_operator(NSArray *stringArray, int *ip; id object; - ip = cond ? stringArray : mutStringArray; // expected-error{{from incompatible type 'NSArray *'}} - ip = cond ? mutStringArray : stringArray; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? stringArray : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = cond ? mutStringArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = cond ? stringArray2 : mutStringArray; // expected-error{{from incompatible type 'NSArray *'}} - ip = cond ? mutStringArray : stringArray2; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? stringArray2 : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = cond ? mutStringArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = cond ? stringArray : mutArray; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? stringArray : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = cond ? stringArray2 : mutArray; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? stringArray2 : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = cond ? mutArray : stringArray; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? mutArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} - ip = cond ? mutArray : stringArray2; // expected-error{{from incompatible type 'NSArray *'}} + ip = cond ? mutArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray *' and 'NSArray *')}} } @@ -357,14 +357,14 @@ void test_ternary_operator(NSArray *stringArray, @implementation NSStringArray - (void)useSuperMethod { int *ip; - ip = super.lastObject; // expected-error{{from incompatible type 'NSString *'}} - ip = [super objectAtIndexedSubscript:0]; // expected-error{{from incompatible type 'NSString *'}} + ip = super.lastObject; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} + ip = [super objectAtIndexedSubscript:0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}} } + (void)useSuperMethod { int *ip; - ip = super.array; // expected-error{{from incompatible type 'NSArray *'}} - ip = [super array]; // expected-error{{from incompatible type 'NSArray *'}} + ip = super.array; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} + ip = [super array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}} } @end diff --git a/clang/test/SemaObjCXX/property-invalid-type.mm b/clang/test/SemaObjCXX/property-invalid-type.mm index 648235894ec43..9122426f4c300 100644 --- a/clang/test/SemaObjCXX/property-invalid-type.mm +++ b/clang/test/SemaObjCXX/property-invalid-type.mm @@ -13,7 +13,7 @@ @implementation I @synthesize response; - (void) foo :(A*) a // expected-error {{expected a type}} { - self.response = a; // expected-error{{assigning to 'int *' from incompatible type 'id'}} + self.response = a; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}} } @end diff --git a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl index 5efea216346aa..a5a8382413476 100644 --- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl +++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl @@ -178,7 +178,7 @@ void test_conversion(__global int *arg_glob, __local int *arg_loc, #if !__OPENCL_CPP_VERSION__ // expected-error@-3{{assigning '__global int *__private' to '__constant int *__private' changes address space of pointer}} #else -// expected-error@-5{{assigning to '__constant int *' from incompatible type '__global int *__private'}} +// expected-error@-5{{assigning '__global int *__private' to '__constant int *' changes address space of pointer}} #endif #endif @@ -187,7 +187,7 @@ void test_conversion(__global int *arg_glob, __local int *arg_loc, #if !__OPENCL_CPP_VERSION__ // expected-error-re@-3{{assigning '__local int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}} #else -// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__local int *__private'}} +// expected-error-re@-5{{assigning '__local int *__private' to '__{{global|constant}} int *' changes address space of pointer}} #endif #endif @@ -196,7 +196,7 @@ void test_conversion(__global int *arg_glob, __local int *arg_loc, #if !__OPENCL_CPP_VERSION__ // expected-error-re@-3{{assigning '__constant int *__private' to '__{{global|generic}} int *__private' changes address space of pointer}} #else -// expected-error-re@-5{{assigning to '__{{global|generic}} int *' from incompatible type '__constant int *__private'}} +// expected-error-re@-5{{assigning '__constant int *__private' to '__{{global|generic}} int *' changes address space of pointer}} #endif #endif @@ -205,7 +205,7 @@ void test_conversion(__global int *arg_glob, __local int *arg_loc, #if !__OPENCL_CPP_VERSION__ // expected-error-re@-3{{assigning '__private int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}} #else -// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__private int *__private'}} +// expected-error-re@-5{{assigning '__private int *__private' to '__{{global|constant}} int *' changes address space of pointer}} #endif #endif @@ -214,7 +214,7 @@ void test_conversion(__global int *arg_glob, __local int *arg_loc, #if !__OPENCL_CPP_VERSION__ // expected-error-re@-3{{assigning '__generic int *__private' to '__{{global|constant}} int *__private' changes address space of pointer}} #else -// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__generic int *__private'}} +// expected-error-re@-5{{assigning '__generic int *__private' to '__{{global|constant}} int *' changes address space of pointer}} #endif #endif @@ -518,7 +518,7 @@ void test_pointer_chains() { #if !__OPENCL_CPP_VERSION__ // expected-error@-3 {{assigning '__local int *__local *__private' to '__generic int *__generic *__private' changes address space of nested pointer}} #else -// expected-error@-5 {{assigning to '__generic int *__generic *' from incompatible type '__local int *__local *__private'}} +// expected-error@-5 {{assigning '__local int *__local *__private' to '__generic int *__generic *' changes address space of nested pointer}} #endif #endif diff --git a/clang/test/SemaOpenCL/address-spaces.cl b/clang/test/SemaOpenCL/address-spaces.cl index 07547ea196804..e9825fd1682aa 100644 --- a/clang/test/SemaOpenCL/address-spaces.cl +++ b/clang/test/SemaOpenCL/address-spaces.cl @@ -20,7 +20,7 @@ __kernel void foo(__global int *gip) { #if !__OPENCL_CPP_VERSION__ // expected-error@-2 {{assigning '__constant int *' to '__generic int *__private' changes address space of pointer}} #else -// expected-error@-4 {{assigning to '__generic int *' from incompatible type '__constant int *'}} +// expected-error@-4 {{assigning '__constant int *' to '__generic int *' changes address space of pointer}} #endif #endif } @@ -176,46 +176,46 @@ void nested(__global int *g, __global int * __private *gg, __local int *l, __loc } #else void nested(__global int *g, __global int * __private *gg, __local int *l, __local int * __private *ll, __global float * __private *gg_f) { - g = gg; // expected-error {{assigning to '__global int *' from incompatible type '__global int *__private *__private'}} - g = l; // expected-error {{assigning to '__global int *' from incompatible type '__local int *__private'}} - g = ll; // expected-error {{assigning to '__global int *' from incompatible type '__local int *__private *__private'}} - g = gg_f; // expected-error {{assigning to '__global int *' from incompatible type '__global float *__private *__private'}} + g = gg; // expected-error {{assigning '__global int *__private *__private' to '__global int *' changes address space of pointer}} + g = l; // expected-error {{assigning '__local int *__private' to '__global int *' changes address space of pointer}} + g = ll; // expected-error {{assigning '__local int *__private *__private' to '__global int *' changes address space of pointer}} + g = gg_f; // expected-error {{assigning '__global float *__private *__private' to '__global int *' changes address space of pointer}} g = (__global int *)gg_f; // expected-error {{C-style cast from '__global float *__private *' to '__global int *' converts between mismatching address spaces}} - gg = g; // expected-error {{assigning to '__global int *__private *' from incompatible type '__global int *__private'; take the address with &}} - gg = l; // expected-error {{assigning to '__global int *__private *' from incompatible type '__local int *__private'}} - gg = ll; // expected-error {{assigning to '__global int *__private *' from incompatible type '__local int *__private *__private'}} - gg = gg_f; // expected-error {{assigning to '__global int *__private *' from incompatible type '__global float *__private *__private'}} + gg = g; // expected-error {{assigning '__global int *__private' to '__global int *__private *' changes address space of pointer}} + gg = l; // expected-error {{assigning '__local int *__private' to '__global int *__private *' changes address space of pointer}} + gg = ll; // expected-error {{assigning '__local int *__private *__private' to '__global int *__private *' changes address space of nested pointer}} + gg = gg_f; // expected-error {{incompatible pointer types assigning to '__global int *__private *' from '__global float *__private *__private'}} gg = (__global int * __private *)gg_f; - l = g; // expected-error {{assigning to '__local int *' from incompatible type '__global int *__private'}} - l = gg; // expected-error {{assigning to '__local int *' from incompatible type '__global int *__private *__private'}} - l = ll; // expected-error {{assigning to '__local int *' from incompatible type '__local int *__private *__private'}} - l = gg_f; // expected-error {{assigning to '__local int *' from incompatible type '__global float *__private *__private'}} + l = g; // expected-error {{assigning '__global int *__private' to '__local int *' changes address space of pointer}} + l = gg; // expected-error {{assigning '__global int *__private *__private' to '__local int *' changes address space of pointer}} + l = ll; // expected-error {{assigning '__local int *__private *__private' to '__local int *' changes address space of pointer}} + l = gg_f; // expected-error {{assigning '__global float *__private *__private' to '__local int *' changes address space of pointer}} l = (__local int *)gg_f; // expected-error {{C-style cast from '__global float *__private *' to '__local int *' converts between mismatching address spaces}} - ll = g; // expected-error {{assigning to '__local int *__private *' from incompatible type '__global int *__private'}} - ll = gg; // expected-error {{assigning to '__local int *__private *' from incompatible type '__global int *__private *__private'}} - ll = l; // expected-error {{assigning to '__local int *__private *' from incompatible type '__local int *__private'; take the address with &}} - ll = gg_f; // expected-error {{assigning to '__local int *__private *' from incompatible type '__global float *__private *__private'}} + ll = g; // expected-error {{assigning '__global int *__private' to '__local int *__private *' changes address space of pointer}} + ll = gg; // expected-error {{assigning '__global int *__private *__private' to '__local int *__private *' changes address space of nested pointer}} + ll = l; // expected-error {{assigning '__local int *__private' to '__local int *__private *' changes address space of pointer}} + ll = gg_f; // expected-error {{assigning '__global float *__private *__private' to '__local int *__private *' changes address space of nested pointer}} ll = (__local int *__private *)gg; //expected-warning{{C-style cast from '__global int *__private *' to '__local int *__private *' changes address space of nested pointers}} - gg_f = g; // expected-error {{assigning to '__global float *__private *' from incompatible type '__global int *__private'}} - gg_f = gg; // expected-error {{assigning to '__global float *__private *' from incompatible type '__global int *__private *__private'}} - gg_f = l; // expected-error {{assigning to '__global float *__private *' from incompatible type '__local int *__private'}} - gg_f = ll; // expected-error {{assigning to '__global float *__private *' from incompatible type '__local int *__private *__private'}} + gg_f = g; // expected-error {{assigning '__global int *__private' to '__global float *__private *' changes address space of pointer}} + gg_f = gg; // expected-error {{incompatible pointer types assigning to '__global float *__private *' from '__global int *__private *__private'}} + gg_f = l; // expected-error {{assigning '__local int *__private' to '__global float *__private *' changes address space of pointer}} + gg_f = ll; // expected-error {{assigning '__local int *__private *__private' to '__global float *__private *' changes address space of nested pointer}} gg_f = (__global float * __private *)gg; typedef __local int * l_t; typedef __global int * g_t; __private l_t * pl; __private g_t * pg; - gg = pl; // expected-error {{assigning to '__global int *__private *' from incompatible type '__private l_t *__private' (aka '__local int *__private *__private')}} - pl = gg; // expected-error {{assigning to '__private l_t *' (aka '__local int *__private *') from incompatible type '__global int *__private *__private'}} + gg = pl; // expected-error {{assigning '__private l_t *__private' (aka '__local int *__private *__private') to '__global int *__private *' changes address space of nested pointer}} + pl = gg; // expected-error {{assigning '__global int *__private *__private' to '__private l_t *' (aka '__local int *__private *') changes address space of nested pointer}} gg = pg; pg = gg; - pg = pl; // expected-error {{assigning to '__private g_t *' (aka '__global int *__private *') from incompatible type '__private l_t *__private' (aka '__local int *__private *__private')}} - pl = pg; // expected-error {{assigning to '__private l_t *' (aka '__local int *__private *') from incompatible type '__private g_t *__private' (aka '__global int *__private *__private')}} + pg = pl; // expected-error {{assigning '__private l_t *__private' (aka '__local int *__private *__private') to '__private g_t *' (aka '__global int *__private *') changes address space of nested pointer}} + pl = pg; // expected-error {{assigning '__private g_t *__private' (aka '__global int *__private *__private') to '__private l_t *' (aka '__local int *__private *') changes address space of nested pointer}} ll = (__local int * __private *)(void *)gg; void *vp = ll; diff --git a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl index dd89f40761c00..e593b21ec4591 100644 --- a/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ b/clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -71,11 +71,25 @@ kernel void basic_conversion() { int4 i4; f = convert_float(d); - d = convert_double_sat_rtp(f); + d = convert_double_rtp(f); l2 = convert_long2_rtz(c2); i4 = convert_int4_sat(f4); } +kernel void basic_conversion_neg() { + int i; + float f; + + f = convert_float_sat(i); +#if !defined(__OPENCL_CPP_VERSION__) + // expected-error@-2{{implicit declaration of function 'convert_float_sat' is invalid in OpenCL}} + // expected-error@-3{{implicit conversion from 'int' to 'float' may lose precision}} +#else + // expected-error@-5{{use of undeclared identifier 'convert_float_sat'; did you mean 'convert_float'?}} + // expected-note@-6{{'convert_float' declared here}} +#endif +} + char4 test_int(char c, char4 c4) { char m = max(c, c); char4 m4 = max(c4, c4); diff --git a/clang/test/SemaSYCL/fpga_pipes.cpp b/clang/test/SemaSYCL/fpga_pipes.cpp index a682a8b63ff63..9cbf7ae5469df 100644 --- a/clang/test/SemaSYCL/fpga_pipes.cpp +++ b/clang/test/SemaSYCL/fpga_pipes.cpp @@ -14,3 +14,35 @@ using type4 = __attribute__((pipe(0))) const int; // expected-error@+1{{'pipe' attribute takes one argument}} using type5 = __attribute__((pipe)) const int; + +struct pipe_storage {}; + +// no error expected +const pipe_storage Storage1 __attribute__((io_pipe_id(1))); + +// expected-error@+1{{'io_pipe_id' attribute requires a non-negative integral compile time constant expression}} +const pipe_storage Storage2 __attribute__((io_pipe_id(-11))); + +// expected-error@+1{{'io_pipe_id' attribute requires an integer constant}} +const pipe_storage Storage3 __attribute__((io_pipe_id("abc"))); + +// expected-error@+1{{'io_pipe_id' attribute only applies to SYCL pipe storage declaration}} +int Storage4 __attribute__((io_pipe_id(5))); + +// expected-error@+2{{'io_pipe_id' attribute requires a non-negative integral compile time constant expression}} +template +pipe_storage Storage5 __attribute__((io_pipe_id(N))); + +template +__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { + kernelFunc(); +} + +void foo(pipe_storage PS) {} + +int main() { + // no error expected + foo(Storage5<2>); + // expected-note@+1{{in instantiation of variable template specialization 'Storage5' requested here}} + foo(Storage5<-1>); +} diff --git a/clang/test/SemaSYCL/sycl-device-static-restrict.cpp b/clang/test/SemaSYCL/sycl-device-static-restrict.cpp new file mode 100644 index 0000000000000..fce763a4a978c --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-static-restrict.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -fsycl-is-device %s +const int glob1 = 1; +int glob2 = 2; +template +__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { + // expected-note-re@+1{{called by 'kernel_single_task}} + kernelFunc(); +} + +int main() { + static int n = 0; + const static int l = 0; + kernel_single_task([]() { + int m = l; + m = glob1; + // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} + m = n; + // expected-error@+1{{SYCL kernel cannot use a non-const global variable}} + m = glob2; + }); + return 0; +} diff --git a/clang/test/SemaSYCL/sycl-restrict.cpp b/clang/test/SemaSYCL/sycl-restrict.cpp index ddafc09c7175d..1a296f6db7d28 100644 --- a/clang/test/SemaSYCL/sycl-restrict.cpp +++ b/clang/test/SemaSYCL/sycl-restrict.cpp @@ -2,40 +2,39 @@ // RUN: %clang_cc1 -fcxx-exceptions -triple spir64 -fsycl-is-device -fno-sycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s // RUN: %clang_cc1 -fcxx-exceptions -triple spir64 -fsycl-is-device -DALLOW_FP=1 -fsycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -std=c++17 %s - namespace std { - class type_info; - typedef __typeof__(sizeof(int)) size_t; -} +class type_info; +typedef __typeof__(sizeof(int)) size_t; +} // namespace std namespace Check_User_Operators { -class Fraction -{ - // expected-error@+2 {{SYCL kernel cannot call a recursive function}} - // expected-note@+1 {{function implemented using recursion declared here}} - int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } - int n, d; +class Fraction { + // expected-error@+2 {{SYCL kernel cannot call a recursive function}} + // expected-note@+1 {{function implemented using recursion declared here}} + int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } + int n, d; + public: - Fraction(int n, int d = 1) : n(n/gcd(n, d)), d(d/gcd(n, d)) { } - int num() const { return n; } - int den() const { return d; } + Fraction(int n, int d = 1) : n(n / gcd(n, d)), d(d / gcd(n, d)) {} + int num() const { return n; } + int den() const { return d; } }; -bool operator==(const Fraction& lhs, const Fraction& rhs) -{ - new int; // expected-error {{SYCL kernel cannot allocate storage}} - return lhs.num() == rhs.num() && lhs.den() == rhs.den(); -}} +bool operator==(const Fraction &lhs, const Fraction &rhs) { + new int; // expected-error {{SYCL kernel cannot allocate storage}} + return lhs.num() == rhs.num() && lhs.den() == rhs.den(); +} +} // namespace Check_User_Operators namespace Check_VLA_Restriction { void no_restriction(int p) { - int index[p+2]; + int index[p + 2]; } void restriction(int p) { // expected-error@+1 {{variable length arrays are not supported for the current target}} - int index[p+2]; -} + int index[p + 2]; } +} // namespace Check_VLA_Restriction -void* operator new (std::size_t size, void* ptr) throw() { return ptr; }; +void *operator new(std::size_t size, void *ptr) throw() { return ptr; }; namespace Check_RTTI_Restriction { struct A { virtual ~A(){}; @@ -50,37 +49,38 @@ struct OverloadedNewDelete { void *operator new(std::size_t size) throw() { // expected-error@+1 {{SYCL kernel cannot allocate storage}} float *pt = new float; - return 0;} + return 0; + } // This overload does not allocate: no diagnostic. - void *operator new[](std::size_t size) throw() {return 0;} + void *operator new[](std::size_t size) throw() { return 0; } void operator delete(void *){}; void operator delete[](void *){}; }; bool isa_B(A *a) { Check_User_Operators::Fraction f1(3, 8), f2(1, 2), f3(10, 2); - // expected-note@+1 {{called by 'isa_B'}} - if (f1 == f2) return false; + if (f1 == f2) + return false; Check_VLA_Restriction::restriction(7); // expected-error@+1 {{SYCL kernel cannot allocate storage}} int *ip = new int; - int i; int *p3 = new(&i) int; // no error on placement new + int i; + int *p3 = new (&i) int; // no error on placement new // expected-note@+1 {{called by 'isa_B'}} - OverloadedNewDelete *x = new( struct OverloadedNewDelete ); - auto y = new struct OverloadedNewDelete [5]; + OverloadedNewDelete *x = new (struct OverloadedNewDelete); + auto y = new struct OverloadedNewDelete[5]; // expected-error@+1 {{SYCL kernel cannot use rtti}} (void)typeid(int); // expected-error@+1 {{SYCL kernel cannot use rtti}} return dynamic_cast(a) != 0; } -template +template __attribute__((sycl_kernel)) void kernel1(L l) { - // expected-note@+1 3{{called by 'kernel1([]() { Check_RTTI_Restriction::A *a; - // expected-note@+1 3{{called by 'operator()'}} Check_RTTI_Restriction::isa_B(a); }); // expected-error@+1 {{__float128 is not supported on this target}} @@ -151,55 +144,64 @@ void usage(myFuncDef functionPtr) { } namespace ns { - int glob; +int glob; } extern "C++" { - int another_global = 5; - namespace AnotherNS { - int moar_globals = 5; - } +int another_global = 5; +namespace AnotherNS { +int moar_globals = 5; +} } int addInt(int n, int m) { - return n+m; + return n + m; } -int use2 ( a_type ab, a_type *abp ) { +int use2(a_type ab, a_type *abp) { - if (ab.constexpr_stat_member) return 2; - if (ab.const_stat_member) return 1; + if (ab.constexpr_stat_member) + return 2; + if (ab.const_stat_member) + return 1; // expected-error@+1 {{SYCL kernel cannot use a non-const static data variable}} - if (ab.stat_member) return 0; + if (ab.stat_member) + return 0; // expected-error@+1 {{SYCL kernel cannot use a non-const static data variable}} - if (abp->stat_member) return 0; - if (ab.fm()) return 0; - // expected-error@+1 {{SYCL kernel cannot use a global variable}} - return another_global ; - // expected-error@+1 {{SYCL kernel cannot use a global variable}} + if (abp->stat_member) + return 0; + // expected-note@+1 {{called by 'use2'}} + if (ab.fm()) + return 0; + // expected-error@+1 {{SYCL kernel cannot use a non-const global variable}} + return another_global; + // expected-error@+1 {{SYCL kernel cannot use a non-const global variable}} return ns::glob + - // expected-error@+1 {{SYCL kernel cannot use a global variable}} - AnotherNS::moar_globals; + // expected-error@+1 {{SYCL kernel cannot use a non-const global variable}} + AnotherNS::moar_globals; + // expected-note@+1 {{called by 'use2'}} eh_not_ok(); - Check_RTTI_Restriction:: A *a; - Check_RTTI_Restriction:: isa_B(a); + Check_RTTI_Restriction::A *a; + // expected-note@+1 2{{called by 'use2'}} + Check_RTTI_Restriction::isa_B(a); + // expected-note@+1 {{called by 'use2'}} usage(&addInt); Check_User_Operators::Fraction f1(3, 8), f2(1, 2), f3(10, 2); - if (f1 == f2) return false; + // expected-note@+1 {{called by 'use2'}} + if (f1 == f2) + return false; } template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { - // expected-note@+1 5{{called by 'kernel_single_task([]() { usage( &addInt ); }); + kernel_single_task([]() { usage(&addInt); }); return 0; } - diff --git a/clang/test/SemaSYCL/tls_error.cpp b/clang/test/SemaSYCL/tls_error.cpp index d029b8c3f83e0..5f8e14c6d1a76 100644 --- a/clang/test/SemaSYCL/tls_error.cpp +++ b/clang/test/SemaSYCL/tls_error.cpp @@ -5,10 +5,10 @@ extern __thread void (*__once_call)(); // expected-no-error void usage() { // expected-error@+2{{thread-local storage is not supported for the current target}} - // expected-error@+1{{SYCL kernel cannot use a global variable}} + // expected-error@+1{{SYCL kernel cannot use a non-const global variable}} __once_callable = 0; // expected-error@+3{{thread-local storage is not supported for the current target}} - // expected-error@+2{{SYCL kernel cannot use a global variable}} + // expected-error@+2{{SYCL kernel cannot use a non-const global variable}} // expected-error@+1{{SYCL kernel cannot call through a function pointer}} __once_call(); } diff --git a/clang/test/SemaTemplate/extern-templates.cpp b/clang/test/SemaTemplate/extern-templates.cpp index acbc9d57122ef..efc4690bbb2c6 100644 --- a/clang/test/SemaTemplate/extern-templates.cpp +++ b/clang/test/SemaTemplate/extern-templates.cpp @@ -23,9 +23,9 @@ extern template class X0; template void X0::Inner::g(T t) { #ifdef MS - t = 17; // expected-error{{assigning to 'long *' from incompatible}} expected-error{{assigning to 'int *' from incompatible}} + t = 17; // expected-error{{incompatible integer to pointer conversion assigning to 'long *'}} expected-error{{incompatible integer to pointer conversion assigning to 'int *'}} #else - t = 17; // expected-error{{assigning to 'long *' from incompatible}} + t = 17; // expected-error{{incompatible integer to pointer conversion assigning to 'long *'}} #endif } diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp index 5a9e2e30e8519..efaa40036598e 100644 --- a/clang/test/SemaTemplate/instantiate-member-class.cpp +++ b/clang/test/SemaTemplate/instantiate-member-class.cpp @@ -43,8 +43,8 @@ X::X *xi; // expected-error{{qualified reference to 'X' is a constructor na X::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type}} void test_naming() { - c1 = c2; // expected-error{{assigning to 'X::C *' from incompatible type 'X::C *'}} - xi = xf; // expected-error{{assigning to 'X::X *' from incompatible type 'X::X *'}} + c1 = c2; // expected-error{{incompatible pointer types assigning to 'X::C *' from 'X::C *'}} + xi = xf; // expected-error{{incompatible pointer types assigning to 'X::X *' from 'X::X *'}} // FIXME: error above doesn't print the type X::X cleanly! } diff --git a/clang/test/SemaTemplate/member-access-expr.cpp b/clang/test/SemaTemplate/member-access-expr.cpp index ef10d72a0ef80..36d6022577289 100644 --- a/clang/test/SemaTemplate/member-access-expr.cpp +++ b/clang/test/SemaTemplate/member-access-expr.cpp @@ -156,7 +156,7 @@ namespace test6 { void get(B **ptr) { // It's okay if at some point we figure out how to diagnose this // at instantiation time. - *ptr = field; // expected-error {{assigning to 'test6::B *' from incompatible type 'test6::A *}} + *ptr = field; // expected-error {{incompatible pointer types assigning to 'test6::B *' from 'test6::A *'}} } }; } diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp index 08ed7d5004ad8..245b9a60269d4 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -194,7 +194,7 @@ namespace EntityReferenced { template struct Y { static void f(T x) { - x = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}} + x = 1; // expected-error{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}} } }; diff --git a/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp b/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp index 0f994c107340f..944256e857c7a 100644 --- a/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp +++ b/clang/unittests/AST/ASTImporterGenericRedeclTest.cpp @@ -35,6 +35,15 @@ struct Class { } }; +struct EnumClass { + using DeclTy = EnumDecl; + static constexpr auto *Prototype = "enum class X;"; + static constexpr auto *Definition = "enum class X {};"; + BindableMatcher getPattern() { + return enumDecl(hasName("X"), unless(isImplicit())); + } +}; + struct Variable { using DeclTy = VarDecl; static constexpr auto *Prototype = "extern int X;"; @@ -65,6 +74,21 @@ struct ClassTemplate { } }; +struct VariableTemplate { + using DeclTy = VarTemplateDecl; + static constexpr auto *Prototype = "template extern T X;"; + static constexpr auto *Definition = + R"( + template T X; + template <> int X; + )"; + // There is no matcher for varTemplateDecl so use a work-around. + BindableMatcher getPattern() { + return namedDecl(hasName("X"), unless(isImplicit()), + has(templateTypeParmDecl())); + } +}; + struct FunctionTemplateSpec { using DeclTy = FunctionDecl; static constexpr auto *Prototype = @@ -406,6 +430,9 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Class, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, EnumClass, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Variable, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) @@ -415,6 +442,9 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, ClassTemplate, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( + RedeclChain, VariableTemplate, , + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, FunctionTemplateSpec, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) @@ -426,12 +456,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -441,12 +475,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -456,12 +494,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitionAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitionAfterImportedPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -471,12 +513,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeAfterImportedDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeAfterImportedDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -485,12 +531,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypes) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , @@ -499,12 +549,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitions) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitions) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , @@ -514,12 +568,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportDefinitionThenPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitionThenPrototype) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -529,12 +587,16 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypeThenDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, EnumClass, , + ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeThenDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, , @@ -546,6 +608,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , WholeRedeclChainIsImportedAtOnce) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , WholeRedeclChainIsImportedAtOnce) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + WholeRedeclChainIsImportedAtOnce) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , WholeRedeclChainIsImportedAtOnce) @@ -555,6 +619,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeThenProtoAndDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeThenProtoAndDefinition) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, , + ImportPrototypeThenProtoAndDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , ImportPrototypeThenProtoAndDefinition) @@ -562,12 +628,16 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainEnumClass, + DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariableTemplate, + DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec, DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec, diff --git a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp index 6a2aa2bfc328b..2bd62e23ea38d 100644 --- a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp +++ b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp @@ -64,6 +64,14 @@ struct Enum { Language getLang() { return Lang_CXX; } }; +struct EnumClass { + using DeclTy = EnumDecl; + static constexpr auto *Definition = "enum class X { a, b };"; + static constexpr auto *ConflictingDefinition = "enum class X { a, b, c };"; + BindableMatcher getPattern() { return enumDecl(hasName("X")); } + Language getLang() { return Lang_CXX11; } +}; + struct EnumConstant { using DeclTy = EnumConstantDecl; static constexpr auto *Definition = "enum E { X = 0 };"; @@ -396,6 +404,9 @@ ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( Enum, Liberal, , ImportConflictingDefAfterDef) +ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( + EnumClass, Liberal, , + ImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( EnumConstant, Liberal, , ImportConflictingDefAfterDef) @@ -434,6 +445,9 @@ ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( Enum, Conservative, , DontImportConflictingDefAfterDef) +ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( + EnumClass, Conservative, , + DontImportConflictingDefAfterDef) ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( EnumConstant, Conservative, , DontImportConflictingDefAfterDef) @@ -595,6 +609,9 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumConservative, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P( + ODRViolationTests, EnumClassConservative, + DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumConstantConservative, DefaultTestValuesForRunOptions, ); @@ -640,6 +657,9 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumLiberal, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P( + ODRViolationTests, EnumClassLiberal, + DefaultTestValuesForRunOptions, ); INSTANTIATE_TEST_CASE_P( ODRViolationTests, EnumConstantLiberal, DefaultTestValuesForRunOptions, ); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 3e8f804374f45..6c1d878235629 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5845,6 +5845,48 @@ TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) { EXPECT_TRUE(isa(To->getReturnType())); } +struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {}; + +TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) { + // Tests that the FileID tree structure (with the links being the include + // chains) is preserved while importing other files (which need to be + // added to this structure with fake include locations. + + SourceLocation Location1; + { + auto Pattern = varDecl(hasName("X")); + Decl *FromTU = getTuDecl("int X;", Lang_C, "input0.c"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + Location1 = Import(FromD, Lang_C)->getLocation(); + } + SourceLocation Location2; + { + auto Pattern = varDecl(hasName("Y")); + Decl *FromTU = getTuDecl("int Y;", Lang_C, "input1.c"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + Location2 = Import(FromD, Lang_C)->getLocation(); + } + + SourceManager &ToSM = ToAST->getSourceManager(); + FileID FileID1 = ToSM.getFileID(Location1); + FileID FileID2 = ToSM.getFileID(Location2); + + // Check that the imported files look like as if they were included from the + // start of the main file. + SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID()); + EXPECT_NE(FileID1, ToSM.getMainFileID()); + EXPECT_NE(FileID2, ToSM.getMainFileID()); + EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart); + EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart); + + // Let the SourceManager check the order of the locations. The order should + // be the order in which the declarations are imported. + EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2)); + EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1)); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions, ); @@ -5903,5 +5945,8 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables, INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportSourceLocations, + DefaultTestValuesForRunOptions, ); + } // end namespace ast_matchers } // end namespace clang diff --git a/clang/unittests/AST/ASTImporterVisibilityTest.cpp b/clang/unittests/AST/ASTImporterVisibilityTest.cpp index d00829f5cfee7..14a6706cc7617 100644 --- a/clang/unittests/AST/ASTImporterVisibilityTest.cpp +++ b/clang/unittests/AST/ASTImporterVisibilityTest.cpp @@ -69,6 +69,8 @@ const auto *AnonC = "namespace { class X; }"; // EnumDecl: const auto *ExternE = "enum E {};"; const auto *AnonE = "namespace { enum E {}; }"; +const auto *ExternEC = "enum class E;"; +const auto *AnonEC = "namespace { enum class E; }"; // TypedefNameDecl: const auto *ExternTypedef = "typedef int T;"; const auto *AnonTypedef = "namespace { typedef int T; }"; @@ -125,6 +127,7 @@ class ImportVisibilityChain using ImportFunctionsVisibilityChain = ImportVisibilityChain; using ImportVariablesVisibilityChain = ImportVisibilityChain; using ImportClassesVisibilityChain = ImportVisibilityChain; +using ImportScopedEnumsVisibilityChain = ImportVisibilityChain; using ImportFunctionTemplatesVisibilityChain = ImportVisibilityChain; using ImportClassTemplatesVisibilityChain = @@ -142,6 +145,10 @@ TEST_P(ImportVariablesVisibilityChain, ImportChain) { TEST_P(ImportClassesVisibilityChain, ImportChain) { TypedTest_ImportChain(); } +// Value-parameterized test for scoped enums. +TEST_P(ImportScopedEnumsVisibilityChain, ImportChain) { + TypedTest_ImportChain(); +} // Value-parameterized test for function templates. TEST_P(ImportFunctionTemplatesVisibilityChain, ImportChain) { TypedTest_ImportChain(); @@ -173,6 +180,11 @@ INSTANTIATE_TEST_CASE_P( ::testing::Combine( DefaultTestValuesForRunOptions, ::testing::Values(ExternC, AnonC)), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportScopedEnumsVisibilityChain, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values(ExternEC, AnonEC)), ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplatesVisibilityChain, ::testing::Combine(DefaultTestValuesForRunOptions, @@ -291,6 +303,7 @@ using ImportFunctionsVisibility = ImportVisibility; using ImportVariablesVisibility = ImportVisibility; using ImportClassesVisibility = ImportVisibility; using ImportEnumsVisibility = ImportVisibility; +using ImportScopedEnumsVisibility = ImportVisibility; using ImportTypedefNameVisibility = ImportVisibility; using ImportFunctionTemplatesVisibility = ImportVisibility; using ImportClassTemplatesVisibility = ImportVisibility; @@ -323,6 +336,12 @@ TEST_P(ImportEnumsVisibility, ImportAfter) { TEST_P(ImportEnumsVisibility, ImportAfterImport) { TypedTest_ImportAfterImportWithMerge(); } +TEST_P(ImportScopedEnumsVisibility, ImportAfter) { + TypedTest_ImportAfter(); +} +TEST_P(ImportScopedEnumsVisibility, ImportAfterImport) { + TypedTest_ImportAfterImport(); +} // TypedefNameDecl. TEST_P(ImportTypedefNameVisibility, ImportAfter) { TypedTest_ImportAfterWithMerge(); @@ -392,6 +411,15 @@ INSTANTIATE_TEST_CASE_P( std::make_tuple(ExternE, AnonE, ExpectUnlinkedDeclChain), std::make_tuple(AnonE, ExternE, ExpectUnlinkedDeclChain), std::make_tuple(AnonE, AnonE, ExpectUnlinkedDeclChain))), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportScopedEnumsVisibility, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values( + std::make_tuple(ExternEC, ExternEC, ExpectLinkedDeclChain), + std::make_tuple(ExternEC, AnonEC, ExpectUnlinkedDeclChain), + std::make_tuple(AnonEC, ExternEC, ExpectUnlinkedDeclChain), + std::make_tuple(AnonEC, AnonEC, ExpectUnlinkedDeclChain))), ); INSTANTIATE_TEST_CASE_P( ParameterizedTests, ImportTypedefNameVisibility, ::testing::Combine( diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 3e94dde80e8a5..2972fc91b9084 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1123,6 +1123,19 @@ TEST(MatchBinaryOperator, HasOperatorName) { EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr)); } +TEST(MatchBinaryOperator, HasAnyOperatorName) { + StatementMatcher Matcher = + binaryOperator(hasAnyOperatorName("+", "-", "*", "/")); + + EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher)); + EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher)); + // Ensure '+= isn't mistaken. + EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher)); +} + TEST(MatchBinaryOperator, HasLHSAndHasRHS) { StatementMatcher OperatorTrueFalse = binaryOperator(hasLHS(cxxBoolLiteral(equals(true))), @@ -1255,6 +1268,18 @@ TEST(MatchUnaryOperator, HasOperatorName) { EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot)); } +TEST(MatchUnaryOperator, HasAnyOperatorName) { + StatementMatcher Matcher = unaryOperator(hasAnyOperatorName("-", "*", "++")); + + EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher)); + EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher)); + EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher)); + EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher)); + EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher)); + EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher)); +} + TEST(MatchUnaryOperator, HasUnaryOperand) { StatementMatcher OperatorOnFalse = unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false)))); diff --git a/clang/unittests/ASTMatchers/CMakeLists.txt b/clang/unittests/ASTMatchers/CMakeLists.txt index 09c4290fa1d21..aa5438c947f40 100644 --- a/clang/unittests/ASTMatchers/CMakeLists.txt +++ b/clang/unittests/ASTMatchers/CMakeLists.txt @@ -16,6 +16,7 @@ add_clang_unittest(ASTMatchersTests ASTMatchersNodeTest.cpp ASTMatchersNarrowingTest.cpp ASTMatchersTraversalTest.cpp + GtestMatchersTest.cpp ) clang_target_link_libraries(ASTMatchersTests diff --git a/clang/unittests/ASTMatchers/GtestMatchersTest.cpp b/clang/unittests/ASTMatchers/GtestMatchersTest.cpp new file mode 100644 index 0000000000000..e5abb24cb4aba --- /dev/null +++ b/clang/unittests/ASTMatchers/GtestMatchersTest.cpp @@ -0,0 +1,191 @@ +//===- unittests/ASTMatchers/GTestMatchersTest.cpp - GTest matcher unit tests // +// +// 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 "ASTMatchersTest.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/GtestMatchers.h" + +namespace clang { +namespace ast_matchers { + +constexpr llvm::StringLiteral GtestMockDecls = R"cc( + static int testerr; + +#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + switch (0) \ + case 0: \ + default: // NOLINT + +#define GTEST_NONFATAL_FAILURE_(code) testerr = code + +#define GTEST_FATAL_FAILURE_(code) testerr = code + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const int gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar) + + // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. + // Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure) + +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) + +#define EXPECT_EQ(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) +#define EXPECT_NE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) + +#define ASSERT_EQ(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) +#define ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) + + namespace testing { + namespace internal { + class EqHelper { + public: + // This templatized version is for the general case. + template + static int Compare(const char* lhs_expression, const char* rhs_expression, + const T1& lhs, const T2& rhs) { + return 0; + } + }; + template + int CmpHelperNE(const char* expr1, const char* expr2, const T1& val1, + const T2& val2) { + return 0; + } + template + int CmpHelperGE(const char* expr1, const char* expr2, const T1& val1, + const T2& val2) { + return 0; + } + template + int CmpHelperGT(const char* expr1, const char* expr2, const T1& val1, + const T2& val2) { + return 0; + } + template + int CmpHelperLE(const char* expr1, const char* expr2, const T1& val1, + const T2& val2) { + return 0; + } + template + int CmpHelperLT(const char* expr1, const char* expr2, const T1& val1, + const T2& val2) { + return 0; + } + } // namespace internal + } // namespace testing +)cc"; + +static std::string wrapGtest(llvm::StringRef Input) { + return (GtestMockDecls + Input).str(); +} + +TEST(GtestAssertTest, ShouldMatchAssert) { + std::string Input = R"cc( + void Test() { ASSERT_EQ(1010, 4321); } + )cc"; + EXPECT_TRUE(matches(wrapGtest(Input), + gtestAssert(GtestCmp::Eq, integerLiteral(equals(1010)), + integerLiteral(equals(4321))))); +} + +TEST(GtestAssertTest, ShouldNotMatchExpect) { + std::string Input = R"cc( + void Test() { EXPECT_EQ(2, 3); } + )cc"; + EXPECT_TRUE( + notMatches(wrapGtest(Input), gtestAssert(GtestCmp::Eq, expr(), expr()))); +} + +TEST(GtestAssertTest, ShouldMatchNestedAssert) { + std::string Input = R"cc( + #define WRAPPER(a, b) ASSERT_EQ(a, b) + void Test() { WRAPPER(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestAssert(GtestCmp::Eq, expr(), expr()))); +} + +TEST(GtestExpectTest, ShouldMatchExpect) { + std::string Input = R"cc( + void Test() { EXPECT_EQ(1010, 4321); } + )cc"; + EXPECT_TRUE(matches(wrapGtest(Input), + gtestExpect(GtestCmp::Eq, integerLiteral(equals(1010)), + integerLiteral(equals(4321))))); +} + +TEST(GtestExpectTest, ShouldNotMatchAssert) { + std::string Input = R"cc( + void Test() { ASSERT_EQ(2, 3); } + )cc"; + EXPECT_TRUE( + notMatches(wrapGtest(Input), gtestExpect(GtestCmp::Eq, expr(), expr()))); +} + +TEST(GtestExpectTest, NeShouldMatchExpectNe) { + std::string Input = R"cc( + void Test() { EXPECT_NE(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestExpect(GtestCmp::Ne, expr(), expr()))); +} + +TEST(GtestExpectTest, LeShouldMatchExpectLe) { + std::string Input = R"cc( + void Test() { EXPECT_LE(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestExpect(GtestCmp::Le, expr(), expr()))); +} + +TEST(GtestExpectTest, LtShouldMatchExpectLt) { + std::string Input = R"cc( + void Test() { EXPECT_LT(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestExpect(GtestCmp::Lt, expr(), expr()))); +} + +TEST(GtestExpectTest, GeShouldMatchExpectGe) { + std::string Input = R"cc( + void Test() { EXPECT_GE(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestExpect(GtestCmp::Ge, expr(), expr()))); +} + +TEST(GtestExpectTest, GtShouldMatchExpectGt) { + std::string Input = R"cc( + void Test() { EXPECT_GT(2, 3); } + )cc"; + EXPECT_TRUE( + matches(wrapGtest(Input), gtestExpect(GtestCmp::Gt, expr(), expr()))); +} + +} // end namespace ast_matchers +} // end namespace clang diff --git a/clang/unittests/Format/CleanupTest.cpp b/clang/unittests/Format/CleanupTest.cpp index b0c81b509d2ae..70741d239c828 100644 --- a/clang/unittests/Format/CleanupTest.cpp +++ b/clang/unittests/Format/CleanupTest.cpp @@ -151,6 +151,31 @@ TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) { EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code)); } +// regression test for bug 39310 +TEST_F(CleanupTest, CtorInitializationSimpleRedundantCommaInFunctionTryBlock) { + std::string Code = "class A {\nA() try : , {} };"; + std::string Expected = "class A {\nA() try {} };"; + EXPECT_EQ(Expected, cleanupAroundOffsets({21, 23}, Code)); + + Code = "class A {\nA() try : x(1), {} };"; + Expected = "class A {\nA() try : x(1) {} };"; + EXPECT_EQ(Expected, cleanupAroundOffsets({27}, Code)); + + Code = "class A {\nA() try :,,,,{} };"; + Expected = "class A {\nA() try {} };"; + EXPECT_EQ(Expected, cleanupAroundOffsets({19}, Code)); + + Code = "class A {\nA() try : x(1),,, {} };"; + Expected = "class A {\nA() try : x(1) {} };"; + EXPECT_EQ(Expected, cleanupAroundOffsets({27}, Code)); + + // Do not remove every comma following a colon as it simply doesn't make + // sense in some situations. + Code = "try : , {}"; + Expected = "try : , {}"; + EXPECT_EQ(Expected, cleanupAroundOffsets({8}, Code)); +} + TEST_F(CleanupTest, CtorInitializationSimpleRedundantColon) { std::string Code = "class A {\nA() : =default; };"; std::string Expected = "class A {\nA() =default; };"; diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp index e859aeb0d22d4..68a8e9fefe2d5 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -240,18 +240,12 @@ TEST_F(FormatTestCSharp, Attributes) { verifyFormat("[TestMethod]\n" "public string Host\n" - "{\n" - " set;\n" - " get;\n" - "}"); + "{ set; get; }"); verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server " "listening on provided host\")]\n" "public string Host\n" - "{\n" - " set;\n" - " get;\n" - "}"); + "{ set; get; }"); verifyFormat( "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n" @@ -513,7 +507,7 @@ var x = foo(className, $@"some code: TEST_F(FormatTestCSharp, CSharpObjectInitializers) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); - // Start code fragemnts with a comment line so that C++ raw string literals + // Start code fragments with a comment line so that C++ raw string literals // as seen are identical to expected formatted code. verifyFormat(R"(// @@ -539,5 +533,47 @@ Shape[] shapes = new[] {new Circle {Radius = 2.7281, Colour = Colours.Red}, Style); } +TEST_F(FormatTestCSharp, CSharpNamedArguments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + + verifyFormat(R"(// +PrintOrderDetails(orderNum: 31, productName: "Red Mug", + sellerName: "Gift Shop");)", + Style); + + // Ensure that trailing comments do not cause problems. + verifyFormat(R"(// +PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment + sellerName: "Gift Shop");)", + Style); +} + +TEST_F(FormatTestCSharp, CSharpPropertyAccessors) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + + verifyFormat("int Value { get }", Style); + verifyFormat("int Value { get; }", Style); + verifyFormat("int Value { internal get; }", Style); + verifyFormat("int Value { get; } = 0", Style); + verifyFormat("int Value { set }", Style); + verifyFormat("int Value { set; }", Style); + verifyFormat("int Value { internal set; }", Style); + verifyFormat("int Value { set; } = 0", Style); + verifyFormat("int Value { get; set }", Style); + verifyFormat("int Value { set; get }", Style); + verifyFormat("int Value { get; private set; }", Style); + verifyFormat("int Value { get; set; }", Style); + verifyFormat("int Value { get; set; } = 0", Style); + verifyFormat("int Value { internal get; internal set; }", Style); + + // Do not wrap expression body definitions. + verifyFormat(R"(// +public string Name { + get => _name; + set => _name = value; +})", + Style); +} + } // namespace format } // end namespace clang diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp index 068b30ebfa8af..52744e101f926 100644 --- a/clang/unittests/Index/IndexTests.cpp +++ b/clang/unittests/Index/IndexTests.cpp @@ -319,6 +319,21 @@ TEST(IndexTest, InjecatedNameClass) { WrittenAt(Position(4, 14))))); } +TEST(IndexTest, VisitDefaultArgs) { + std::string Code = R"cpp( + int var = 0; + void f(int s = var) {} + )cpp"; + auto Index = std::make_shared(); + IndexingOptions Opts; + Opts.IndexFunctionLocals = true; + Opts.IndexParametersInDeclarations = true; + tooling::runToolOnCode(std::make_unique(Index, Opts), Code); + EXPECT_THAT(Index->Symbols, + Contains(AllOf(QName("var"), HasRole(SymbolRole::Reference), + WrittenAt(Position(3, 20))))); +} + } // namespace } // namespace index } // namespace clang diff --git a/clang/unittests/Rename/RenameClassTest.cpp b/clang/unittests/Rename/RenameClassTest.cpp index 04a9138f741ff..1c00ad7912e73 100644 --- a/clang/unittests/Rename/RenameClassTest.cpp +++ b/clang/unittests/Rename/RenameClassTest.cpp @@ -780,7 +780,8 @@ TEST_F(RenameClassTest, UsingAlias) { CompareSnippets(Expected, After); } -TEST_F(ClangRenameTest, NestedTemplates) { +// FIXME: investigate why the test fails when adding a new USR to the USRSet. +TEST_F(ClangRenameTest, DISABLED_NestedTemplates) { std::string Before = R"( namespace a { template struct A {}; } a::A> foo;)"; diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 59c9b4fb38631..0ff66206e06e1 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -101,6 +101,15 @@ bool FindClassDeclX(ASTUnit *AST) { } return false; } + +struct TestDiagnosticConsumer : public DiagnosticConsumer { + TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {} + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override { + ++NumDiagnosticsSeen; + } + unsigned NumDiagnosticsSeen; +}; } // end namespace TEST(runToolOnCode, FindsClassDecl) { @@ -129,6 +138,16 @@ TEST(buildASTFromCode, FindsClassDecl) { EXPECT_FALSE(FindClassDeclX(AST.get())); } +TEST(buildASTFromCode, ReportsErrors) { + TestDiagnosticConsumer Consumer; + std::unique_ptr AST = buildASTFromCodeWithArgs( + "int x = \"A\";", {}, "input.cc", "clang-tool", + std::make_shared(), + getClangStripDependencyFileAdjuster(), FileContentMappings(), &Consumer); + EXPECT_TRUE(AST.get()); + EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen); +} + TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) { std::unique_ptr Factory( newFrontendActionFactory()); @@ -639,15 +658,6 @@ TEST(ClangToolTest, BuildASTs) { EXPECT_EQ(2u, ASTs.size()); } -struct TestDiagnosticConsumer : public DiagnosticConsumer { - TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {} - void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info) override { - ++NumDiagnosticsSeen; - } - unsigned NumDiagnosticsSeen; -}; - TEST(ClangToolTest, InjectDiagnosticConsumer) { FixedCompilationDatabase Compilations("/", std::vector()); ClangTool Tool(Compilations, std::vector(1, "/a.cc")); diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index f6072336a701f..6a34f1ff1b24a 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -1188,6 +1188,18 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope, } else { PrintFatalError("unsignedflag's argument should be a scalar type"); } + } else if (Op->getName() == "bitsize") { + if (D->getNumArgs() != 1) + PrintFatalError("bitsize should have exactly one argument"); + Record *TypeRec = cast(D->getArg(0))->getDef(); + if (!TypeRec->isSubClassOf("Type")) + PrintFatalError("bitsize's argument should be a type"); + if (const auto *ST = dyn_cast(getType(TypeRec, Param))) { + return std::make_shared(getScalarType("u32"), + ST->sizeInBits()); + } else { + PrintFatalError("bitsize's argument should be a scalar type"); + } } else { std::vector Args; for (unsigned i = 0, e = D->getNumArgs(); i < e; ++i) diff --git a/clang/www/analyzer/alpha_checks.html b/clang/www/analyzer/alpha_checks.html index 3d4075e5aaf9c..181ce1b9de591 100644 --- a/clang/www/analyzer/alpha_checks.html +++ b/clang/www/analyzer/alpha_checks.html @@ -1083,9 +1083,6 @@

Non-determinism Alpha Checkers

f(i); } - - -