diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 77ba81c58c5d63..76b8266cae87c4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -125,3 +125,6 @@ clang/test/AST/Interp/ @tbaederr /llvm/**/TextAPI/ @cyndyishida /clang/**/InstallAPI/ @cyndyishida /clang/tools/clang-installapi/ @cyndyishida + +# ExtractAPI +/clang/**/ExtractAPI @daniel-grumberg diff --git a/.github/workflows/email-check.yaml b/.github/workflows/email-check.yaml index ac53b5e527b094..8f32d020975f5d 100644 --- a/.github/workflows/email-check.yaml +++ b/.github/workflows/email-check.yaml @@ -1,7 +1,7 @@ name: "Check for private emails used in PRs" on: - pull_request_target: + pull_request: types: - opened @@ -10,8 +10,6 @@ permissions: jobs: validate_email: - permissions: - pull-requests: write runs-on: ubuntu-latest if: github.repository == 'llvm/llvm-project' steps: @@ -25,20 +23,24 @@ jobs: run: | git log -1 echo "EMAIL=$(git show -s --format='%ae' HEAD~0)" >> $GITHUB_OUTPUT + # Create empty comment file + echo "[]" > comments - name: Validate author email if: ${{ endsWith(steps.author.outputs.EMAIL, 'noreply.github.com') }} - uses: actions/github-script@v6 env: - EMAIL: ${{ steps.author.outputs.EMAIL }} + COMMENT: >- + ⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
+ Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
+ See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. + run: | + cat << EOF > comments + [{"body" : "$COMMENT"}] + EOF + + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() with: - script: | - const { EMAIL } = process.env - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: `⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo. - Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account. - See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. - `}) + name: workflow-args + path: | + comments diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml index 02a5f7c213e898..e003be006c4e15 100644 --- a/.github/workflows/issue-write.yml +++ b/.github/workflows/issue-write.yml @@ -2,7 +2,9 @@ name: Comment on an issue on: workflow_run: - workflows: ["Check code formatting"] + workflows: + - "Check code formatting" + - "Check for private emails used in PRs" types: - completed @@ -31,7 +33,7 @@ jobs: script: | var fs = require('fs'); const comments = JSON.parse(fs.readFileSync('./comments')); - if (!comments) { + if (!comments || comments.length == 0) { return; } @@ -77,6 +79,15 @@ jobs: } const gql_result = await github.graphql(gql_query, gql_variables); console.log(gql_result); + // If the branch for the PR was deleted before this job has a chance + // to run, then the ref will be null. This can happen if someone: + // 1. Rebase the PR, which triggers some workflow. + // 2. Immediately merges the PR and deletes the branch. + // 3. The workflow finishes and triggers this job. + if (!gql_result.repository.ref) { + console.log("Ref has been deleted"); + return; + } console.log(gql_result.repository.ref.associatedPullRequests.nodes); var pr_number = 0; diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 0bf7386a309840..d5f6fa407b825e 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -32,7 +32,7 @@ jobs: - name: Fetch code formatting utils uses: actions/checkout@v4 with: - reository: ${{ github.repository }} + repository: ${{ github.repository }} ref: ${{ github.base_ref }} sparse-checkout: | llvm/utils/git/requirements_formatting.txt diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 5089f849128010..bc047fefa3151c 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -1168,7 +1168,7 @@ class BinaryFunction { /// Pass an offset of the entry point in the input binary and a corresponding /// global symbol to the callback function. /// - /// Return true of all callbacks returned true, false otherwise. + /// Return true if all callbacks returned true, false otherwise. bool forEachEntryPoint(EntryPointCallbackTy Callback) const; /// Return MC symbol associated with the end of the function. diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 5728c9970fb65d..dd772d69202548 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangTidyReadabilityModule DeleteNullPointerCheck.cpp DuplicateIncludeCheck.cpp ElseAfterReturnCheck.cpp + EnumInitialValueCheck.cpp FunctionCognitiveComplexityCheck.cpp FunctionSizeCheck.cpp IdentifierLengthCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp new file mode 100644 index 00000000000000..8f2841c32259a2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp @@ -0,0 +1,200 @@ +//===--- EnumInitialValueCheck.cpp - clang-tidy ---------------------------===// +// +// 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 "EnumInitialValueCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { + return ECD->getInitExpr() == nullptr; + }); +} + +static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) { + bool IsFirst = true; + for (const EnumConstantDecl *ECD : Node.enumerators()) { + if ((IsFirst && ECD->getInitExpr() == nullptr) || + (!IsFirst && ECD->getInitExpr() != nullptr)) + return false; + IsFirst = false; + } + return !IsFirst; +} + +static bool areAllEnumeratorsInitialized(const EnumDecl &Node) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { + return ECD->getInitExpr() != nullptr; + }); +} + +/// Check if \p Enumerator is initialized with a (potentially negated) \c +/// IntegerLiteral. +static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) { + const Expr *const Init = Enumerator->getInitExpr(); + if (!Init) + return false; + return Init->isIntegerConstantExpr(Enumerator->getASTContext()); +} + +static void cleanInitialValue(DiagnosticBuilder &Diag, + const EnumConstantDecl *ECD, + const SourceManager &SM, + const LangOptions &LangOpts) { + const SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange(); + if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() || + InitExprRange.getEnd().isMacroID()) + return; + std::optional EqualToken = utils::lexer::findNextTokenSkippingComments( + ECD->getLocation(), SM, LangOpts); + if (!EqualToken.has_value() || + EqualToken.value().getKind() != tok::TokenKind::equal) + return; + const SourceLocation EqualLoc{EqualToken->getLocation()}; + if (EqualLoc.isInvalid() || EqualLoc.isMacroID()) + return; + Diag << FixItHint::CreateRemoval(EqualLoc) + << FixItHint::CreateRemoval(InitExprRange); + return; +} + +namespace { + +AST_MATCHER(EnumDecl, isMacro) { + SourceLocation Loc = Node.getBeginLoc(); + return Loc.isMacroID(); +} + +AST_MATCHER(EnumDecl, hasConsistentInitialValues) { + return isNoneEnumeratorsInitialized(Node) || + isOnlyFirstEnumeratorInitialized(Node) || + areAllEnumeratorsInitialized(Node); +} + +AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) { + const EnumDecl::enumerator_range Enumerators = Node.enumerators(); + if (Enumerators.empty()) + return false; + const EnumConstantDecl *ECD = *Enumerators.begin(); + return isOnlyFirstEnumeratorInitialized(Node) && + isInitializedByLiteral(ECD) && ECD->getInitVal().isZero(); +} + +/// Excludes bitfields because enumerators initialized with the result of a +/// bitwise operator on enumeration values or any other expr that is not a +/// potentially negative integer literal. +/// Enumerations where it is not directly clear if they are used with +/// bitmask, evident when enumerators are only initialized with (potentially +/// negative) integer literals, are ignored. This is also the case when all +/// enumerators are powers of two (e.g., 0, 1, 2). +AST_MATCHER(EnumDecl, hasSequentialInitialValues) { + const EnumDecl::enumerator_range Enumerators = Node.enumerators(); + if (Enumerators.empty()) + return false; + const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin(); + llvm::APSInt PrevValue = FirstEnumerator->getInitVal(); + if (!isInitializedByLiteral(FirstEnumerator)) + return false; + bool AllEnumeratorsArePowersOfTwo = true; + for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) { + const llvm::APSInt NewValue = Enumerator->getInitVal(); + if (NewValue != ++PrevValue) + return false; + if (!isInitializedByLiteral(Enumerator)) + return false; + PrevValue = NewValue; + AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2(); + } + return !AllEnumeratorsArePowersOfTwo; +} + +} // namespace + +EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + AllowExplicitZeroFirstInitialValue( + Options.get("AllowExplicitZeroFirstInitialValue", true)), + AllowExplicitSequentialInitialValues( + Options.get("AllowExplicitSequentialInitialValues", true)) {} + +void EnumInitialValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "AllowExplicitZeroFirstInitialValue", + AllowExplicitZeroFirstInitialValue); + Options.store(Opts, "AllowExplicitSequentialInitialValues", + AllowExplicitSequentialInitialValues); +} + +void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + enumDecl(unless(isMacro()), unless(hasConsistentInitialValues())) + .bind("inconsistent"), + this); + if (!AllowExplicitZeroFirstInitialValue) + Finder->addMatcher( + enumDecl(hasZeroInitialValueForFirstEnumerator()).bind("zero_first"), + this); + if (!AllowExplicitSequentialInitialValues) + Finder->addMatcher(enumDecl(unless(isMacro()), hasSequentialInitialValues()) + .bind("sequential"), + this); +} + +void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *Enum = Result.Nodes.getNodeAs("inconsistent")) { + DiagnosticBuilder Diag = + diag(Enum->getBeginLoc(), + "inital values in enum %0 are not consistent, consider explicit " + "initialization of all, none or only the first enumerator") + << Enum; + for (const EnumConstantDecl *ECD : Enum->enumerators()) + if (ECD->getInitExpr() == nullptr) { + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( + ECD->getLocation(), 0, *Result.SourceManager, getLangOpts()); + if (EndLoc.isMacroID()) + continue; + llvm::SmallString<8> Str{" = "}; + ECD->getInitVal().toString(Str); + Diag << FixItHint::CreateInsertion(EndLoc, Str); + } + return; + } + + if (const auto *Enum = Result.Nodes.getNodeAs("zero_first")) { + const EnumConstantDecl *ECD = *Enum->enumerator_begin(); + const SourceLocation Loc = ECD->getLocation(); + if (Loc.isInvalid() || Loc.isMacroID()) + return; + DiagnosticBuilder Diag = diag(Loc, "zero initial value for the first " + "enumerator in %0 can be disregarded") + << Enum; + cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); + return; + } + if (const auto *Enum = Result.Nodes.getNodeAs("sequential")) { + DiagnosticBuilder Diag = + diag(Enum->getBeginLoc(), + "sequential initial value in %0 can be ignored") + << Enum; + for (const EnumConstantDecl *ECD : llvm::drop_begin(Enum->enumerators())) + cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); + return; + } +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h new file mode 100644 index 00000000000000..66087e4ee170da --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h @@ -0,0 +1,38 @@ +//===--- EnumInitialValueCheck.h - clang-tidy -------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Enforces consistent style for enumerators' initialization, covering three +/// styles: none, first only, or all initialized explicitly. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability/enum-initial-value.html +class EnumInitialValueCheck : public ClangTidyCheck { +public: + EnumInitialValueCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + +private: + const bool AllowExplicitZeroFirstInitialValue; + const bool AllowExplicitSequentialInitialValues; +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index bca2c425111f6c..376b84683df74e 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -22,6 +22,7 @@ #include "DeleteNullPointerCheck.h" #include "DuplicateIncludeCheck.h" #include "ElseAfterReturnCheck.h" +#include "EnumInitialValueCheck.h" #include "FunctionCognitiveComplexityCheck.h" #include "FunctionSizeCheck.h" #include "IdentifierLengthCheck.h" @@ -92,6 +93,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-duplicate-include"); CheckFactories.registerCheck( "readability-else-after-return"); + CheckFactories.registerCheck( + "readability-enum-initial-value"); CheckFactories.registerCheck( "readability-function-cognitive-complexity"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 78b09d23d4427f..309b844615a121 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -123,6 +123,12 @@ New checks Finds initializer lists for aggregate types that could be written as designated initializers instead. +- New :doc:`readability-enum-initial-value + ` check. + + Enforces consistent style for enumerators' initialization, covering three + styles: none, first only, or all initialized explicitly. + - New :doc:`readability-use-std-min-max ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 79e81dd174e4f3..188a42bfddd383 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -352,6 +352,7 @@ Clang-Tidy Checks :doc:`readability-delete-null-pointer `, "Yes" :doc:`readability-duplicate-include `, "Yes" :doc:`readability-else-after-return `, "Yes" + :doc:`readability-enum-initial-value `, "Yes" :doc:`readability-function-cognitive-complexity `, :doc:`readability-function-size `, :doc:`readability-identifier-length `, diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst new file mode 100644 index 00000000000000..660efc1eaff3e5 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst @@ -0,0 +1,75 @@ +.. title:: clang-tidy - readability-enum-initial-value + +readability-enum-initial-value +============================== + +Enforces consistent style for enumerators' initialization, covering three +styles: none, first only, or all initialized explicitly. + +When adding new enumerations, inconsistent initial value will cause potential +enumeration value conflicts. + +In an enumeration, the following three cases are accepted. +1. none of enumerators are explicit initialized. +2. the first enumerator is explicit initialized. +3. all of enumerators are explicit initialized. + +.. code-block:: c++ + + // valid, none of enumerators are initialized. + enum A { + e0, + e1, + e2, + }; + + // valid, the first enumerator is initialized. + enum A { + e0 = 0, + e1, + e2, + }; + + // valid, all of enumerators are initialized. + enum A { + e0 = 0, + e1 = 1, + e2 = 2, + }; + + // invalid, e1 is not explicit initialized. + enum A { + e0 = 0, + e1, + e2 = 2, + }; + +Options +------- + +.. option:: AllowExplicitZeroFirstInitialValue + + If set to `false`, the first enumerator must not be explicitly initialized. + See examples below. Default is `true`. + + .. code-block:: c++ + + enum A { + e0 = 0, // not allowed if AllowExplicitZeroFirstInitialValue is false + e1, + e2, + }; + + +.. option:: AllowExplicitSequentialInitialValues + + If set to `false`, sequential initializations are not allowed. + See examples below. Default is `true`. + + .. code-block:: c++ + + enum A { + e0 = 1, // not allowed if AllowExplicitSequentialInitialValues is false + e1 = 2, + e2 = 3, + }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c new file mode 100644 index 00000000000000..c66288cbe3e957 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c @@ -0,0 +1,80 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t +// RUN: %check_clang_tidy -check-suffix=ENABLE %s readability-enum-initial-value %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-enum-initial-value.AllowExplicitZeroFirstInitialValue: false, \ +// RUN: readability-enum-initial-value.AllowExplicitSequentialInitialValues: false, \ +// RUN: }}' + +enum EError { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EError' are not consistent + EError_a = 1, + EError_b, + // CHECK-FIXES: EError_b = 2, + EError_c = 3, +}; + +enum ENone { + ENone_a, + ENone_b, + EENone_c, +}; + +enum EFirst { + EFirst_a = 1, + EFirst_b, + EFirst_c, +}; + +enum EAll { + EAll_a = 1, + EAll_b = 2, + EAll_c = 4, +}; + +#define ENUMERATOR_1 EMacro1_b +enum EMacro1 { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro1' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro1' are not consistent + EMacro1_a = 1, + ENUMERATOR_1, + // CHECK-FIXES: ENUMERATOR_1 = 2, + EMacro1_c = 3, +}; + + +#define ENUMERATOR_2 EMacro2_b = 2 +enum EMacro2 { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro2' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro2' are not consistent + EMacro2_a = 1, + ENUMERATOR_2, + EMacro2_c, + // CHECK-FIXES: EMacro2_c = 3, +}; + +enum EnumZeroFirstInitialValue { + EnumZeroFirstInitialValue_0 = 0, + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EnumZeroFirstInitialValue' can be disregarded + // CHECK-FIXES-ENABLE: EnumZeroFirstInitialValue_0 , + EnumZeroFirstInitialValue_1, + EnumZeroFirstInitialValue_2, +}; + +enum EnumZeroFirstInitialValueWithComment { + EnumZeroFirstInitialValueWithComment_0 = /* == */ 0, + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EnumZeroFirstInitialValueWithComment' can be disregarded + // CHECK-FIXES-ENABLE: EnumZeroFirstInitialValueWithComment_0 /* == */ , + EnumZeroFirstInitialValueWithComment_1, + EnumZeroFirstInitialValueWithComment_2, +}; + +enum EnumSequentialInitialValue { + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:1: warning: sequential initial value in 'EnumSequentialInitialValue' can be ignored + EnumSequentialInitialValue_0 = 2, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_0 = 2, + EnumSequentialInitialValue_1 = 3, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_1 , + EnumSequentialInitialValue_2 = 4, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_2 , +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp new file mode 100644 index 00000000000000..3c4ba970372a07 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp @@ -0,0 +1,27 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t + +enum class EError { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent + EError_a = 1, + EError_b, + // CHECK-FIXES: EError_b = 2, + EError_c = 3, +}; + +enum class ENone { + ENone_a, + ENone_b, + EENone_c, +}; + +enum class EFirst { + EFirst_a = 1, + EFirst_b, + EFirst_c, +}; + +enum class EAll { + EAll_a = 1, + EAll_b = 2, + EAll_c = 3, +}; diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp index d0efc5ca763753..57d930b26e64c0 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp @@ -25,7 +25,7 @@ // RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s -// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 | FileCheck -check-prefix=CHECK8 -implicit-check-not='{{warning:|error:}}' %s +// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 // CHECK1: error: no input files [clang-diagnostic-error] // CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' [clang-diagnostic-error] @@ -68,6 +68,4 @@ auto S<>::foo(auto) { return 1; } -// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error] -// CHECK8: note: previous declaration is here #endif diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index df69d7d0dd414b..393d97a4cf1a33 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -71,6 +71,8 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH Python3_LIBRARIES Python3_INCLUDE_DIRS Python3_RPATH + SWIG_DIR + SWIG_EXECUTABLE CMAKE_FIND_PACKAGE_PREFER_CONFIG CMAKE_SYSROOT CMAKE_MODULE_LINKER_FLAGS diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 2ee36f24d7ce4b..39f7cded36edbf 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3295,6 +3295,21 @@ the configuration (without a prefix: ``Auto``). +.. _BreakFunctionDefinitionParameters: + +**BreakFunctionDefinitionParameters** (``Boolean``) :versionbadge:`clang-format 19` :ref:`¶ ` + If ``true``, clang-format will always break before function definition + parameters. + + .. code-block:: c++ + + true: + void functionDefinition( + int A, int B) {} + + false: + void functionDefinition(int A, int B) {} + .. _BreakInheritanceList: **BreakInheritanceList** (``BreakInheritanceListStyle``) :versionbadge:`clang-format 7` :ref:`¶ ` diff --git a/clang/docs/HLSL/FunctionCalls.rst b/clang/docs/HLSL/FunctionCalls.rst index 7317de2163f897..6d65fe6e3fb20b 100644 --- a/clang/docs/HLSL/FunctionCalls.rst +++ b/clang/docs/HLSL/FunctionCalls.rst @@ -157,22 +157,23 @@ Clang Implementation of the changes in the prototype implementation are restoring Clang-3.7 code that was previously modified to its original state. -The implementation in clang depends on two new AST nodes and minor extensions to -Clang's existing support for Objective-C write-back arguments. The goal of this -design is to capture the semantic details of HLSL function calls in the AST, and -minimize the amount of magic that needs to occur during IR generation. - -The two new AST nodes are ``HLSLArrayTemporaryExpr`` and ``HLSLOutParamExpr``, -which respectively represent the temporaries used for passing arrays by value -and the temporaries created for function outputs. +The implementation in clang adds a new non-decaying array type, a new AST node +to represent output parameters, and minor extensions to Clang's existing support +for Objective-C write-back arguments. The goal of this design is to capture the +semantic details of HLSL function calls in the AST, and minimize the amount of +magic that needs to occur during IR generation. Array Temporaries ----------------- -The ``HLSLArrayTemporaryExpr`` represents temporary values for input -constant-sized array arguments. This applies for all constant-sized array -arguments regardless of whether or not the parameter is constant-sized or -unsized. +The new ``ArrayParameterType`` is a sub-class of ``ConstantArrayType`` +inheriting all the behaviors and methods of the parent except that it does not +decay to a pointer during overload resolution or template type deduction. + +An argument of ``ConstantArrayType`` can be implicitly converted to an +equivalent non-decayed ``ArrayParameterType`` if the underlying canonical +``ConstantArrayType`` is the same. This occurs during overload resolution +instead of array to pointer decay. .. code-block:: c++ @@ -193,7 +194,7 @@ In the example above, the following AST is generated for the call to CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [4])' | `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' In the example above, the following AST is generated for the call to @@ -204,7 +205,7 @@ In the example above, the following AST is generated for the call to CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [])' | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' In both of these cases the argument expression is of known array size so we can @@ -236,7 +237,7 @@ An expected AST should be something like: CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [])' | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' Out Parameter Temporaries diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 76eaf0bf11c303..3237842fa1ceb1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -253,6 +253,21 @@ Attribute Changes in Clang added a new extension query ``__has_extension(swiftcc)`` corresponding to the ``__attribute__((swiftcc))`` attribute. +- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply + to certain C++ class types, such as smart pointers: + ``void useObject(std::unique_ptr _Nonnull obj);``. + + This works for standard library types including ``unique_ptr``, ``shared_ptr``, + and ``function``. See + `the attribute reference documentation `_ + for the full list. + +- The ``_Nullable`` attribute can be applied to C++ class declarations: + ``template class _Nullable MySmartPointer {};``. + + This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to + apply to this class. + Improvements to Clang's diagnostics ----------------------------------- - Clang now applies syntax highlighting to the code snippets it @@ -313,6 +328,9 @@ Improvements to Clang's diagnostics - New ``-Wformat-signedness`` diagnostic that warn if the format string requires an unsigned argument and the argument is signed and vice versa. +- Clang now emits ``unused argument`` warning when the -fmodule-output flag is used + with an input that is not of type c++-module. + Improvements to Clang's time-trace ---------------------------------- @@ -468,6 +486,11 @@ Bug Fixes to C++ Support following the first `::` were ignored). - Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). +- Fixed a bug that prevented member function templates of class templates declared with a deduced return type + from being explicitly specialized for a given implicit instantiation of the class template. + +- Fix crash when inheriting from a cv-qualified type. Fixes: + (`#35603 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 002f36ecbbaa3f..08f71051e6cbf3 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -260,6 +260,9 @@ class ASTContext : public RefCountedBase { ASTContext&> SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + ArrayParameterTypes; + /// The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. @@ -1367,6 +1370,10 @@ class ASTContext : public RefCountedBase { /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a specified array parameter type from the + /// original array type. + QualType getArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to the atomic type for the specified /// type. QualType getAtomicType(QualType T) const; diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 6e153ebe024b42..2bfefeabc348be 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3163,23 +3163,12 @@ class CallExpr : public Expr { } }; -/// Extra data stored in some MemberExpr objects. -struct MemberExprNameQualifier { - /// The nested-name-specifier that qualifies the name, including - /// source-location information. - NestedNameSpecifierLoc QualifierLoc; - - /// The DeclAccessPair through which the MemberDecl was found due to - /// name qualifiers. - DeclAccessPair FoundDecl; -}; - /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr final : public Expr, - private llvm::TrailingObjects { friend class ASTReader; friend class ASTStmtReader; @@ -3201,26 +3190,30 @@ class MemberExpr final /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; - size_t numTrailingObjects(OverloadToken) const { - return hasQualifierOrFoundDecl(); + size_t numTrailingObjects(OverloadToken) const { + return hasQualifier(); + } + + size_t numTrailingObjects(OverloadToken) const { + return hasFoundDecl(); } size_t numTrailingObjects(OverloadToken) const { return hasTemplateKWAndArgsInfo(); } - bool hasQualifierOrFoundDecl() const { - return MemberExprBits.HasQualifierOrFoundDecl; - } + bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; } bool hasTemplateKWAndArgsInfo() const { return MemberExprBits.HasTemplateKWAndArgsInfo; } MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, - ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, ExprObjectKind OK, - NonOdrUseReason NOUR); + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + ValueDecl *MemberDecl, DeclAccessPair FoundDecl, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, QualType T, + ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR); MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} @@ -3264,24 +3257,24 @@ class MemberExpr final /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { - if (!hasQualifierOrFoundDecl()) + if (!hasFoundDecl()) return DeclAccessPair::make(getMemberDecl(), getMemberDecl()->getAccess()); - return getTrailingObjects()->FoundDecl; + return *getTrailingObjects(); } /// Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return getQualifier() != nullptr; } + bool hasQualifier() const { return MemberExprBits.HasQualifier; } /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { - if (!hasQualifierOrFoundDecl()) + if (!hasQualifier()) return NestedNameSpecifierLoc(); - return getTrailingObjects()->QualifierLoc; + return *getTrailingObjects(); } /// If the member name was qualified, retrieves the diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index ef05072800f11a..8788b8ff0ef0a4 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -364,6 +364,9 @@ CAST_OPERATION(IntToOCLSampler) // Truncate a vector type by dropping elements from the end (HLSL only). CAST_OPERATION(HLSLVectorTruncation) +// Non-decaying array RValue cast (HLSL only). +CAST_OPERATION(HLSLArrayRValue) + //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. // Note that additions to this should also update the StmtVisitor class, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 4a1ff222ecadcd..8630317795a9ad 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(ConstantArrayType, { TRY_TO(TraverseStmt(const_cast(T->getSizeExpr()))); }) +DEF_TRAVERSE_TYPE(ArrayParameterType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(const_cast(T->getSizeExpr()))); +}) + DEF_TRAVERSE_TYPE(IncompleteArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1260,6 +1266,11 @@ DEF_TRAVERSE_TYPELOC(ConstantArrayType, { TRY_TO(TraverseArrayTypeLocHelper(TL)); }) +DEF_TRAVERSE_TYPELOC(ArrayParameterType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + TRY_TO(TraverseArrayTypeLocHelper(TL)); +}) + DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseArrayTypeLocHelper(TL)); diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 55eca4007d17ea..8892518d58e853 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -583,11 +583,13 @@ class alignas(void *) Stmt { unsigned IsArrow : 1; /// True if this member expression used a nested-name-specifier to - /// refer to the member, e.g., "x->Base::f", or found its member via - /// a using declaration. When true, a MemberExprNameQualifier - /// structure is allocated immediately after the MemberExpr. + /// refer to the member, e.g., "x->Base::f". LLVM_PREFERRED_TYPE(bool) - unsigned HasQualifierOrFoundDecl : 1; + unsigned HasQualifier : 1; + + // True if this member expression found its member via a using declaration. + LLVM_PREFERRED_TYPE(bool) + unsigned HasFoundDecl : 1; /// True if this member expression specified a template keyword /// and/or a template argument list explicitly, e.g., x->f, diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 5d8dde37e76969..99f45d518c7960 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2300,6 +2300,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isConstantArrayType() const; bool isIncompleteArrayType() const; bool isVariableArrayType() const; + bool isArrayParameterType() const; bool isDependentSizedArrayType() const; bool isRecordType() const; bool isClassType() const; @@ -3334,14 +3335,15 @@ class ArrayType : public Type, public llvm::FoldingSetNode { return T->getTypeClass() == ConstantArray || T->getTypeClass() == VariableArray || T->getTypeClass() == IncompleteArray || - T->getTypeClass() == DependentSizedArray; + T->getTypeClass() == DependentSizedArray || + T->getTypeClass() == ArrayParameter; } }; /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType final : public ArrayType { +class ConstantArrayType : public ArrayType { friend class ASTContext; // ASTContext creates these. struct ExternalSize { @@ -3382,6 +3384,19 @@ class ConstantArrayType final : public ArrayType { const Expr *SzExpr, ArraySizeModifier SzMod, unsigned Qual); +protected: + ConstantArrayType(TypeClass Tc, const ConstantArrayType *ATy, QualType Can) + : ArrayType(Tc, ATy->getElementType(), Can, ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue(), nullptr) { + ConstantArrayTypeBits.HasExternalSize = + ATy->ConstantArrayTypeBits.HasExternalSize; + if (!ConstantArrayTypeBits.HasExternalSize) { + ConstantArrayTypeBits.SizeWidth = ATy->ConstantArrayTypeBits.SizeWidth; + Size = ATy->Size; + } else + SizePtr = ATy->SizePtr; + } + public: /// Return the constant array size as an APInt. llvm::APInt getSize() const { @@ -3453,7 +3468,22 @@ class ConstantArrayType final : public ArrayType { ArraySizeModifier SizeMod, unsigned TypeQuals); static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray; + return T->getTypeClass() == ConstantArray || + T->getTypeClass() == ArrayParameter; + } +}; + +/// Represents a constant array type that does not decay to a pointer when used +/// as a function parameter. +class ArrayParameterType : public ConstantArrayType { + friend class ASTContext; // ASTContext creates these. + + ArrayParameterType(const ConstantArrayType *ATy, QualType CanTy) + : ConstantArrayType(ArrayParameter, ATy, CanTy) {} + +public: + static bool classof(const Type *T) { + return T->getTypeClass() == ArrayParameter; } }; @@ -7185,7 +7215,8 @@ inline bool QualType::isCanonicalAsParam() const { if (T->isVariablyModifiedType() && T->hasSizedVLAType()) return false; - return !isa(T) && !isa(T); + return !isa(T) && + (!isa(T) || isa(T)); } inline bool QualType::isConstQualified() const { @@ -7450,6 +7481,10 @@ inline bool Type::isVariableArrayType() const { return isa(CanonicalType); } +inline bool Type::isArrayParameterType() const { + return isa(CanonicalType); +} + inline bool Type::isDependentSizedArrayType() const { return isa(CanonicalType); } @@ -7813,7 +7848,7 @@ inline bool Type::isTypedefNameType() const { /// Determines whether this type can decay to a pointer type. inline bool Type::canDecayToPointerType() const { - return isFunctionType() || isArrayType(); + return isFunctionType() || (isArrayType() && !isArrayParameterType()); } inline bool Type::hasPointerRepresentation() const { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index b09eb3539a4bad..9f2dff7a782cb3 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1611,6 +1611,11 @@ class ConstantArrayTypeLoc : ConstantArrayType> { }; +/// Wrapper for source info for array parameter types. +class ArrayParameterTypeLoc + : public InheritingConcreteTypeLoc< + ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {}; + class IncompleteArrayTypeLoc : public InheritingConcreteTypeLoc; } +let Class = ArrayParameterType in { + def : Creator<[{ return ctx.getAdjustedParameterType( + ctx.getConstantArrayType(elementType,sizeValue, + size,sizeModifier, + indexQualifiers.getCVRQualifiers())); }]>; +} + let Class = IncompleteArrayType in { def : Creator<[{ return ctx.getIncompleteArrayType(elementType, sizeModifier, diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 80e607525a0a37..6584460cf5685e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2178,9 +2178,10 @@ def TypeNonNull : TypeAttr { let Documentation = [TypeNonNullDocs]; } -def TypeNullable : TypeAttr { +def TypeNullable : DeclOrTypeAttr { let Spellings = [CustomKeyword<"_Nullable">]; let Documentation = [TypeNullableDocs]; +// let Subjects = SubjectList<[CXXRecord], ErrorDiag>; } def TypeNullableResult : TypeAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 3ea4d676b4f89d..0ca4ea377fc36a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4151,6 +4151,20 @@ non-underscored keywords. For example: @property (assign, nullable) NSView *superview; @property (readonly, nonnull) NSArray *subviews; @end + +As well as built-in pointer types, the nullability attributes can be attached +to C++ classes marked with the ``_Nullable`` attribute. + +The following C++ standard library types are considered nullable: +``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``, +``move_only_function`` and ``coroutine_handle``. + +Types should be marked nullable only where the type itself leaves nullability +ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because +``optional _Nullable`` is redundant and ``optional _Nonnull`` is +not a useful type. ``std::weak_ptr`` is not nullable, because its nullability +can change with no visible modification, so static annotation is unlikely to be +unhelpful. }]; } @@ -4185,6 +4199,17 @@ The ``_Nullable`` nullability qualifier indicates that a value of the int fetch_or_zero(int * _Nullable ptr); a caller of ``fetch_or_zero`` can provide null. + +The ``_Nullable`` attribute on classes indicates that the given class can +represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers +make sense for this type. For example: + + .. code-block:: c + + class _Nullable ArenaPointer { ... }; + + ArenaPointer _Nonnull x = ...; + ArenaPointer _Nullable y = nullptr; }]; } diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 592ed3bda51506..3d86f7510bde20 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -548,6 +548,12 @@ def err_drv_extract_api_wrong_kind : Error< "header file '%0' input '%1' does not match the type of prior input " "in api extraction; use '-x %2' to override">; +def err_drv_missing_symbol_graph_dir: Error< + "Must provide a symbol graph output directory using --symbol-graph-dir=">; + +def err_drv_unexpected_symbol_graph_output : Error< + "Unexpected output symbol graph '%1'; please provide --symbol-graph-dir= instead">; + def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">, InGroup>; def note_use_dashdash : Note< diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index ba23cf84c5e343..14b08d4927ec5e 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -366,4 +366,8 @@ def warn_profile_data_misexpect : Warning< def err_extract_api_ignores_file_not_found : Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal; +def warn_missing_symbol_graph_dir : Warning< + "Missing symbol graph output directory, defaulting to working directory">, + InGroup; + } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 520168f01fd846..5251774ff4efd6 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1517,3 +1517,5 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon // Warnings and notes InstallAPI verification. def InstallAPIViolation : DiagGroup<"installapi-violation">; +// Warnings about misuse of ExtractAPI options. +def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index b41aadc73f205d..fe4d1c4afcca65 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -94,6 +94,7 @@ EXTENSION(define_target_os_macros, FEATURE(enumerator_attributes, true) FEATURE(nullability, true) FEATURE(nullability_on_arrays, true) +FEATURE(nullability_on_classes, true) FEATURE(nullability_nullable_result, true) FEATURE(memory_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 3625f063758915..fee49cf4326dfc 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -64,6 +64,7 @@ def ConstantArrayType : TypeNode; def IncompleteArrayType : TypeNode; def VariableArrayType : TypeNode; def DependentSizedArrayType : TypeNode, AlwaysDependent; +def ArrayParameterType : TypeNode; def DependentSizedExtVectorType : TypeNode, AlwaysDependent; def DependentAddressSpaceType : TypeNode, AlwaysDependent; def VectorType : TypeNode; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 04eb87f0d5d1aa..c3e90a70925b78 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1507,14 +1507,29 @@ def extract_api : Flag<["-"], "extract-api">, def product_name_EQ: Joined<["--"], "product-name=">, Visibility<[ClangOption, CC1Option]>, MarshallingInfoString>; -def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">, +def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">, Visibility<[ClangOption, CC1Option]>, - HelpText<"Generate Extract API information as a side effect of compilation.">, - MarshallingInfoString>; + HelpText<"Generate Extract API information as a side effect of compilation.">, + MarshallingInfoFlag>; +def emit_extension_symbol_graphs: Flag<["--"], "emit-extension-symbol-graphs">, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Generate additional symbol graphs for extended modules.">, + MarshallingInfoFlag>; def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">, Visibility<[ClangOption, CC1Option]>, HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">, MarshallingInfoStringVector>; +def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Directory in which to emit symbol graphs.">, + MarshallingInfoString>; +def emit_pretty_sgf: Flag<["--"], "pretty-sgf">, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Emit pretty printed symbol graphs">, + MarshallingInfoFlag>; +def emit_sgf_symbol_labels_for_testing: Flag<["--"], "emit-sgf-symbol-labels-for-testing">, + Visibility<[CC1Option]>, + MarshallingInfoFlag>; def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group; def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group, Visibility<[ClangOption, CC1Option]>, @@ -8313,6 +8328,7 @@ def _SLASH_Fi : CLCompileJoined<"Fi">, def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file (with /c)">, MetaVarName<"">; +def _SLASH_Fo_COLON : CLCompileJoined<"Fo:">, Alias<_SLASH_Fo>; def _SLASH_guard : CLJoined<"guard:">, HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks. " "Enable EH Continuation Guard with /guard:ehcont">; diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index b220db294101d8..92cacf65c7d64e 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -20,17 +20,25 @@ #include "clang/AST/Availability.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/DeclarationFragments.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" +#include +#include #include +#include #include namespace clang { @@ -149,15 +157,58 @@ class Template { /// \endcode using DocComment = std::vector; -// Classes deriving from APIRecord need to have USR be the first constructor -// argument. This is so that they are compatible with `addTopLevelRecord` -// defined in API.cpp +struct APIRecord; + +// This represents a reference to another symbol that might come from external +/// sources. +struct SymbolReference { + StringRef Name; + StringRef USR; + + /// The source project/module/product of the referred symbol. + StringRef Source; + + // A Pointer to the APIRecord for this reference if known + const APIRecord *Record = nullptr; + + SymbolReference() = default; + SymbolReference(StringRef Name, StringRef USR, StringRef Source = "") + : Name(Name), USR(USR), Source(Source) {} + SymbolReference(const APIRecord *R); + + /// Determine if this SymbolReference is empty. + /// + /// \returns true if and only if all \c Name, \c USR, and \c Source is empty. + bool empty() const { return Name.empty() && USR.empty() && Source.empty(); } +}; + +class RecordContext; + +// Concrete classes deriving from APIRecord need to have a construct with first +// arguments USR, and Name, in that order. This is so that they +// are compatible with `APISet::createRecord`. +// When adding a new kind of record don't forget to update APIRecords.inc! /// The base representation of an API record. Holds common symbol information. struct APIRecord { /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) enum RecordKind { RK_Unknown, + // If adding a record context record kind here make sure to update + // RecordContext::classof if needed and add a RECORD_CONTEXT entry to + // APIRecords.inc + RK_FirstRecordContext, RK_Namespace, + RK_Enum, + RK_Struct, + RK_Union, + RK_ObjCInterface, + RK_ObjCCategory, + RK_ObjCProtocol, + RK_CXXClass, + RK_ClassTemplate, + RK_ClassTemplateSpecialization, + RK_ClassTemplatePartialSpecialization, + RK_LastRecordContext, RK_GlobalFunction, RK_GlobalFunctionTemplate, RK_GlobalFunctionTemplateSpecialization, @@ -166,18 +217,11 @@ struct APIRecord { RK_GlobalVariableTemplateSpecialization, RK_GlobalVariableTemplatePartialSpecialization, RK_EnumConstant, - RK_Enum, RK_StructField, - RK_Struct, RK_UnionField, - RK_Union, RK_StaticField, RK_CXXField, RK_CXXFieldTemplate, - RK_CXXClass, - RK_ClassTemplate, - RK_ClassTemplateSpecialization, - RK_ClassTemplatePartialSpecialization, RK_Concept, RK_CXXStaticMethod, RK_CXXInstanceMethod, @@ -190,40 +234,15 @@ struct APIRecord { RK_ObjCIvar, RK_ObjCClassMethod, RK_ObjCInstanceMethod, - RK_ObjCInterface, - RK_ObjCCategory, - RK_ObjCCategoryModule, - RK_ObjCProtocol, RK_MacroDefinition, RK_Typedef, }; - /// Stores information about the context of the declaration of this API. - /// This is roughly analogous to the DeclContext hierarchy for an AST Node. - struct HierarchyInformation { - /// The USR of the parent API. - StringRef ParentUSR; - /// The name of the parent API. - StringRef ParentName; - /// The record kind of the parent API. - RecordKind ParentKind = RK_Unknown; - /// A pointer to the parent APIRecord if known. - APIRecord *ParentRecord = nullptr; - - HierarchyInformation() = default; - HierarchyInformation(StringRef ParentUSR, StringRef ParentName, - RecordKind Kind, APIRecord *ParentRecord = nullptr) - : ParentUSR(ParentUSR), ParentName(ParentName), ParentKind(Kind), - ParentRecord(ParentRecord) {} - - bool empty() const { - return ParentUSR.empty() && ParentName.empty() && - ParentKind == RK_Unknown && ParentRecord == nullptr; - } - }; - StringRef USR; StringRef Name; + + SymbolReference Parent; + PresumedLoc Location; AvailabilityInfo Availability; LinkageInfo Linkage; @@ -242,79 +261,169 @@ struct APIRecord { /// Objective-C class/instance methods). DeclarationFragments SubHeading; - /// Information about the parent record of this record. - HierarchyInformation ParentInformation; - /// Whether the symbol was defined in a system header. bool IsFromSystemHeader; + AccessControl Access; + private: const RecordKind Kind; + friend class RecordContext; + // Used to store the next child record in RecordContext. This works because + // APIRecords semantically only have one parent. + mutable APIRecord *NextInContext = nullptr; public: + APIRecord *getNextInContext() const { return NextInContext; } + RecordKind getKind() const { return Kind; } + static APIRecord *castFromRecordContext(const RecordContext *Ctx); + static RecordContext *castToRecordContext(const APIRecord *Record); + APIRecord() = delete; APIRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Location, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - bool IsFromSystemHeader) - : USR(USR), Name(Name), Location(Location), + SymbolReference Parent, PresumedLoc Location, + AvailabilityInfo Availability, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader, + AccessControl Access = AccessControl()) + : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location), Availability(std::move(Availability)), Linkage(Linkage), Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), - IsFromSystemHeader(IsFromSystemHeader), Kind(Kind) {} + IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)), + Kind(Kind) {} APIRecord(RecordKind Kind, StringRef USR, StringRef Name) : USR(USR), Name(Name), Kind(Kind) {} // Pure virtual destructor to make APIRecord abstract virtual ~APIRecord() = 0; + static bool classof(const APIRecord *Record) { return true; } + static bool classofKind(RecordKind K) { return true; } + static bool classof(const RecordContext *Ctx) { return true; } +}; + +/// Base class used for specific record types that have children records this is +/// analogous to the DeclContext for the AST +class RecordContext { +public: + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(APIRecord::RecordKind K) { + return K > APIRecord::RK_FirstRecordContext && + K < APIRecord::RK_LastRecordContext; + } + + static bool classof(const RecordContext *Context) { return true; } + + RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {} + + APIRecord::RecordKind getKind() const { return Kind; } + + struct record_iterator { + private: + APIRecord *Current = nullptr; + + public: + using value_type = APIRecord *; + using reference = const value_type &; + using pointer = const value_type *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + + record_iterator() = default; + explicit record_iterator(value_type R) : Current(R) {} + reference operator*() const { return Current; } + // This doesn't strictly meet the iterator requirements, but it's the + // behavior we want here. + value_type operator->() const { return Current; } + record_iterator &operator++() { + Current = Current->getNextInContext(); + return *this; + } + record_iterator operator++(int) { + record_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(record_iterator x, record_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(record_iterator x, record_iterator y) { + return x.Current != y.Current; + } + }; + + using record_range = llvm::iterator_range; + record_range records() const { + return record_range(records_begin(), records_end()); + } + record_iterator records_begin() const { return record_iterator(First); }; + record_iterator records_end() const { return record_iterator(); } + bool records_empty() const { return First == nullptr; }; + +private: + APIRecord::RecordKind Kind; + mutable APIRecord *First = nullptr; + mutable APIRecord *Last = nullptr; + +protected: + friend class APISet; + void addToRecordChain(APIRecord *) const; }; -struct NamespaceRecord : APIRecord { - NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, +struct NamespaceRecord : APIRecord, RecordContext { + NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + LinkageInfo Linkage, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availability), + : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), + RecordContext(RK_Namespace) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_Namespace; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_Namespace; } }; /// This holds information associated with global functions. struct GlobalFunctionRecord : APIRecord { FunctionSignature Signature; - GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, + GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) - : APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availability), - Linkage, Comment, Declaration, SubHeading, - IsFromSystemHeader), + : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc, + std::move(Availability), Linkage, Comment, Declaration, + SubHeading, IsFromSystemHeader), Signature(Signature) {} GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage, - Comment, Declaration, SubHeading, IsFromSystemHeader), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), + Linkage, Comment, Declaration, SubHeading, + IsFromSystemHeader), Signature(Signature) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalFunction; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; } private: virtual void anchor(); @@ -323,63 +432,74 @@ struct GlobalFunctionRecord : APIRecord { struct GlobalFunctionTemplateRecord : GlobalFunctionRecord { Template Templ; - GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, Template Template, bool IsFromSystemHeader) - : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc, + : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, Signature, IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalFunctionTemplate; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_GlobalFunctionTemplate; } }; struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord { GlobalFunctionTemplateSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) : GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name, - Loc, std::move(Availability), Linkage, Comment, - Declaration, SubHeading, Signature, + Parent, Loc, std::move(Availability), Linkage, + Comment, Declaration, SubHeading, Signature, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalFunctionTemplateSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_GlobalFunctionTemplateSpecialization; } }; /// This holds information associated with global functions. struct GlobalVariableRecord : APIRecord { - GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, + GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_GlobalVariable, USR, Name, Loc, std::move(Availability), - Linkage, Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc, + std::move(Availability), Linkage, Comment, Declaration, + SubHeading, IsFromSystemHeader) {} GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name, + SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage, - Comment, Declaration, SubHeading, IsFromSystemHeader) {} + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), + Linkage, Comment, Declaration, SubHeading, + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalVariable; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; } private: virtual void anchor(); @@ -388,34 +508,42 @@ struct GlobalVariableRecord : APIRecord { struct GlobalVariableTemplateRecord : GlobalVariableRecord { Template Templ; - GlobalVariableTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + GlobalVariableTemplateRecord(StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, class Template Template, bool IsFromSystemHeader) - : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Loc, + : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalVariableTemplate; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_GlobalVariableTemplate; } }; struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord { GlobalVariableTemplateSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) : GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name, - Loc, std::move(Availability), Linkage, Comment, - Declaration, SubHeading, IsFromSystemHeader) {} + Parent, Loc, std::move(Availability), Linkage, + Comment, Declaration, SubHeading, + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalVariableTemplateSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_GlobalVariableTemplateSpecialization; } }; @@ -424,126 +552,203 @@ struct GlobalVariableTemplatePartialSpecializationRecord Template Templ; GlobalVariableTemplatePartialSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, class Template Template, bool IsFromSystemHeader) : GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization, - USR, Name, Loc, std::move(Availability), Linkage, - Comment, Declaration, SubHeading, + USR, Name, Parent, Loc, std::move(Availability), + Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_GlobalVariableTemplatePartialSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_GlobalVariableTemplatePartialSpecialization; } }; /// This holds information associated with enum constants. struct EnumConstantRecord : APIRecord { - EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availability), - LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc, + std::move(Availability), LinkageInfo::none(), Comment, + Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_EnumConstant; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_EnumConstant; } private: virtual void anchor(); }; /// This holds information associated with enums. -struct EnumRecord : APIRecord { - SmallVector> Constants; - - EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - bool IsFromSystemHeader) - : APIRecord(RK_Enum, USR, Name, Loc, std::move(Availability), +struct EnumRecord : APIRecord, RecordContext { + EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), + RecordContext(RK_Enum) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_Enum; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_Enum; } private: virtual void anchor(); }; -/// This holds information associated with struct fields. +/// This holds information associated with struct or union fields fields. struct RecordFieldRecord : APIRecord { - RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, RecordKind Kind, - bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_StructField || - Record->getKind() == RK_UnionField; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_StructField || K == RK_UnionField; } -private: - virtual void anchor(); + virtual ~RecordFieldRecord() = 0; }; -/// This holds information associated with structs. -struct RecordRecord : APIRecord { - SmallVector> Fields; - - RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc, +/// This holds information associated with structs and unions. +struct RecordRecord : APIRecord, RecordContext { + RecordRecord(RecordKind Kind, StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, RecordKind Kind, - bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), + RecordContext(Kind) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_Struct || Record->getKind() == RK_Union; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_Struct || K == RK_Union; } + virtual ~RecordRecord() = 0; +}; + +struct StructFieldRecord : RecordFieldRecord { + StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, IsFromSystemHeader) {} + + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_StructField; } + private: virtual void anchor(); }; -struct CXXFieldRecord : APIRecord { - AccessControl Access; +struct StructRecord : RecordRecord { + StructRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability), + Comment, Declaration, SubHeading, IsFromSystemHeader) {} - CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_Struct; } + +private: + virtual void anchor(); +}; + +struct UnionFieldRecord : RecordFieldRecord { + UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, IsFromSystemHeader) {} + + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_UnionField; } + +private: + virtual void anchor(); +}; + +struct UnionRecord : RecordRecord { + UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability), + Comment, Declaration, SubHeading, IsFromSystemHeader) {} + + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_Union; } + +private: + virtual void anchor(); +}; + +struct CXXFieldRecord : APIRecord { + CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, bool IsFromSystemHeader) - : APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availability), + : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader), - Access(Access) {} + IsFromSystemHeader, std::move(Access)) {} CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader), - Access(Access) {} + IsFromSystemHeader, std::move(Access)) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXField; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField; } private: @@ -553,111 +758,122 @@ struct CXXFieldRecord : APIRecord { struct CXXFieldTemplateRecord : CXXFieldRecord { Template Templ; - CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, Template Template, bool IsFromSystemHeader) - : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc, + : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Access, IsFromSystemHeader), + SubHeading, std::move(Access), IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXFieldTemplate; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; } }; struct CXXMethodRecord : APIRecord { FunctionSignature Signature; - AccessControl Access; CXXMethodRecord() = delete; CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader), - Signature(Signature), Access(Access) {} + IsFromSystemHeader, std::move(Access)), + Signature(Signature) {} virtual ~CXXMethodRecord() = 0; }; struct CXXConstructorRecord : CXXMethodRecord { - CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc, + : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader) {} + SubHeading, Signature, std::move(Access), + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXConstructorMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; } private: virtual void anchor(); }; struct CXXDestructorRecord : CXXMethodRecord { - CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc, + : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader) {} + SubHeading, Signature, std::move(Access), + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXDestructorMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; } private: virtual void anchor(); }; struct CXXStaticMethodRecord : CXXMethodRecord { - CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc, + : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader) {} + SubHeading, Signature, std::move(Access), + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXStaticMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; } private: virtual void anchor(); }; struct CXXInstanceMethodRecord : CXXMethodRecord { - CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc, + : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader) {} + SubHeading, Signature, std::move(Access), + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXInstanceMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; } private: virtual void anchor(); @@ -666,36 +882,42 @@ struct CXXInstanceMethodRecord : CXXMethodRecord { struct CXXMethodTemplateRecord : CXXMethodRecord { Template Templ; - CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, Template Template, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc, + : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader), + SubHeading, Signature, std::move(Access), + IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXMethodTemplate; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; } }; struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord { CXXMethodTemplateSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) - : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader) {} + : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent, + Loc, std::move(Availability), Comment, Declaration, + SubHeading, Signature, std::move(Access), + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_CXXMethodTemplateSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_CXXMethodTemplateSpecialization; } }; @@ -714,13 +936,13 @@ struct ObjCPropertyRecord : APIRecord { bool IsOptional; ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AttributeKind Attributes, StringRef GetterName, StringRef SetterName, bool IsOptional, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader), Attributes(Attributes), GetterName(GetterName), SetterName(SetterName), @@ -733,44 +955,44 @@ struct ObjCPropertyRecord : APIRecord { }; struct ObjCInstancePropertyRecord : ObjCPropertyRecord { - ObjCInstancePropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - AttributeKind Attributes, StringRef GetterName, - StringRef SetterName, bool IsOptional, - bool IsFromSystemHeader) - : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Loc, + ObjCInstancePropertyRecord( + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, + AttributeKind Attributes, StringRef GetterName, StringRef SetterName, + bool IsOptional, bool IsFromSystemHeader) + : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, SubHeading, Attributes, GetterName, SetterName, IsOptional, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCInstanceProperty; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; } private: virtual void anchor(); }; struct ObjCClassPropertyRecord : ObjCPropertyRecord { - ObjCClassPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AttributeKind Attributes, StringRef GetterName, StringRef SetterName, bool IsOptional, bool IsFromSystemHeader) - : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Loc, + : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, SubHeading, Attributes, GetterName, SetterName, IsOptional, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCClassProperty; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; } private: virtual void anchor(); @@ -778,23 +1000,21 @@ struct ObjCClassPropertyRecord : ObjCPropertyRecord { /// This holds information associated with Objective-C instance variables. struct ObjCInstanceVariableRecord : APIRecord { - using AccessControl = ObjCIvarDecl::AccessControl; - AccessControl Access; - - ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + ObjCInstanceVariableRecord(StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - AccessControl Access, bool IsFromSystemHeader) - : APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availability), + bool IsFromSystemHeader) + : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader), - Access(Access) {} + IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCIvar; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; } private: virtual void anchor(); @@ -807,11 +1027,12 @@ struct ObjCMethodRecord : APIRecord { ObjCMethodRecord() = delete; ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader), Signature(Signature) {} @@ -820,122 +1041,103 @@ struct ObjCMethodRecord : APIRecord { }; struct ObjCInstanceMethodRecord : ObjCMethodRecord { - ObjCInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + ObjCInstanceMethodRecord(StringRef USR, StringRef Name, + SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) - : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Loc, + : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, SubHeading, Signature, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCInstanceMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; } private: virtual void anchor(); }; struct ObjCClassMethodRecord : ObjCMethodRecord { - ObjCClassMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, + ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsFromSystemHeader) - : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Loc, + : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, SubHeading, Signature, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCClassMethod; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; } private: virtual void anchor(); }; -/// This represents a reference to another symbol that might come from external -/// sources. -struct SymbolReference { - StringRef Name; - StringRef USR; - - /// The source project/module/product of the referred symbol. - StringRef Source; - - SymbolReference() = default; - SymbolReference(StringRef Name, StringRef USR = "", StringRef Source = "") - : Name(Name), USR(USR), Source(Source) {} - SymbolReference(const APIRecord &Record) - : Name(Record.Name), USR(Record.USR) {} - SymbolReference(const APIRecord *Record) - : Name(Record->Name), USR(Record->USR) {} - - /// Determine if this SymbolReference is empty. - /// - /// \returns true if and only if all \c Name, \c USR, and \c Source is empty. - bool empty() const { return Name.empty() && USR.empty() && Source.empty(); } -}; - struct StaticFieldRecord : CXXFieldRecord { - SymbolReference Context; - - StaticFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, SymbolReference Context, - AccessControl Access, bool IsFromSystemHeader) - : CXXFieldRecord(RK_StaticField, USR, Name, Loc, std::move(Availability), - Comment, Declaration, SubHeading, Access, - IsFromSystemHeader), - Context(Context) {} + StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + LinkageInfo Linkage, const DocComment &Comment, + DeclarationFragments Declaration, + DeclarationFragments SubHeading, AccessControl Access, + bool IsFromSystemHeader) + : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, std::move(Access), IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_StaticField; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_StaticField; } }; /// The base representation of an Objective-C container record. Holds common /// information associated with Objective-C containers. -struct ObjCContainerRecord : APIRecord { - SmallVector> Methods; - SmallVector> Properties; - SmallVector> Ivars; +struct ObjCContainerRecord : APIRecord, RecordContext { SmallVector Protocols; ObjCContainerRecord() = delete; ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name, - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage, - Comment, Declaration, SubHeading, IsFromSystemHeader) {} + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), + Linkage, Comment, Declaration, SubHeading, + IsFromSystemHeader), + RecordContext(Kind) {} virtual ~ObjCContainerRecord() = 0; }; -struct CXXClassRecord : APIRecord { - SmallVector> Fields; - SmallVector> Methods; +struct CXXClassRecord : APIRecord, RecordContext { SmallVector Bases; - AccessControl Access; - CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, + CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, RecordKind Kind, AccessControl Access, bool IsFromSystemHeader) - : APIRecord(Kind, USR, Name, Loc, std::move(Availability), + : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader), - Access(Access) {} + IsFromSystemHeader, std::move(Access)), + RecordContext(Kind) {} static bool classof(const APIRecord *Record) { - return (Record->getKind() == RK_CXXClass); + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_CXXClass || K == RK_ClassTemplate || + K == RK_ClassTemplateSpecialization || + K == RK_ClassTemplatePartialSpecialization; } private: @@ -945,86 +1147,108 @@ struct CXXClassRecord : APIRecord { struct ClassTemplateRecord : CXXClassRecord { Template Templ; - ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, Template Template, AccessControl Access, bool IsFromSystemHeader) - : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment, - Declaration, SubHeading, RK_ClassTemplate, Access, - IsFromSystemHeader), + : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, + Declaration, SubHeading, RK_ClassTemplate, + std::move(Access), IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ClassTemplate; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; } }; struct ClassTemplateSpecializationRecord : CXXClassRecord { ClassTemplateSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, bool IsFromSystemHeader) - : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment, + : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, Declaration, SubHeading, RK_ClassTemplateSpecialization, Access, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ClassTemplateSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_ClassTemplateSpecialization; } }; struct ClassTemplatePartialSpecializationRecord : CXXClassRecord { Template Templ; ClassTemplatePartialSpecializationRecord( - StringRef USR, StringRef Name, PresumedLoc Loc, + StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, Template Template, AccessControl Access, bool IsFromSystemHeader) - : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment, - Declaration, SubHeading, RK_ClassTemplateSpecialization, - Access, IsFromSystemHeader), + : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, + Declaration, SubHeading, + RK_ClassTemplatePartialSpecialization, Access, + IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ClassTemplatePartialSpecialization; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { + return K == RK_ClassTemplatePartialSpecialization; } }; struct ConceptRecord : APIRecord { Template Templ; - ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, + ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, Template Template, bool IsFromSystemHeader) - : APIRecord(RK_Concept, USR, Name, Loc, std::move(Availability), + : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader), Templ(Template) {} + + static bool classof(const APIRecord *Record) { + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_Concept; } }; /// This holds information associated with Objective-C categories. struct ObjCCategoryRecord : ObjCContainerRecord { SymbolReference Interface; - /// Determine whether the Category is derived from external class interface. - bool IsFromExternalModule = false; - ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference Interface, bool IsFromSystemHeader) - : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc, + : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader), Interface(Interface) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCCategory; + return classofKind(Record->getKind()); + } + static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; } + + bool isExtendingExternalModule() const { return !Interface.Source.empty(); } + + std::optional getExtendedExternalModule() const { + if (!isExtendingExternalModule()) + return {}; + return Interface.Source; } private: @@ -1034,23 +1258,22 @@ struct ObjCCategoryRecord : ObjCContainerRecord { /// This holds information associated with Objective-C interfaces/classes. struct ObjCInterfaceRecord : ObjCContainerRecord { SymbolReference SuperClass; - // ObjCCategoryRecord%s are stored in and owned by APISet. - SmallVector Categories; - ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, + ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference SuperClass, bool IsFromSystemHeader) - : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc, + : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader), SuperClass(SuperClass) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCInterface; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; } private: virtual void anchor(); @@ -1058,18 +1281,20 @@ struct ObjCInterfaceRecord : ObjCContainerRecord { /// This holds information associated with Objective-C protocols. struct ObjCProtocolRecord : ObjCContainerRecord { - ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, + ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc, + : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_ObjCProtocol; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; } private: virtual void anchor(); @@ -1077,17 +1302,18 @@ struct ObjCProtocolRecord : ObjCContainerRecord { /// This holds information associated with macro definitions. struct MacroDefinitionRecord : APIRecord { - MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - DeclarationFragments Declaration, + MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(), - LinkageInfo(), {}, Declaration, SubHeading, - IsFromSystemHeader) {} + : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc, + AvailabilityInfo(), LinkageInfo(), {}, Declaration, + SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_MacroDefinition; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; } private: virtual void anchor(); @@ -1101,575 +1327,228 @@ struct MacroDefinitionRecord : APIRecord { struct TypedefRecord : APIRecord { SymbolReference UnderlyingType; - TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, + TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent, + PresumedLoc Loc, AvailabilityInfo Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference UnderlyingType, bool IsFromSystemHeader) - : APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availability), + : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability), LinkageInfo(), Comment, Declaration, SubHeading, IsFromSystemHeader), UnderlyingType(UnderlyingType) {} static bool classof(const APIRecord *Record) { - return Record->getKind() == RK_Typedef; + return classofKind(Record->getKind()); } + static bool classofKind(RecordKind K) { return K == RK_Typedef; } private: virtual void anchor(); }; -/// Check if a record type has a function signature mixin. -/// -/// This is denoted by the record type having a ``Signature`` field of type -/// FunctionSignature. -template -struct has_function_signature : public std::false_type {}; -template <> -struct has_function_signature : public std::true_type {}; -template <> -struct has_function_signature : public std::true_type {}; -template <> -struct has_function_signature - : public std::true_type {}; -template <> -struct has_function_signature : public std::true_type {}; -template <> -struct has_function_signature : public std::true_type {}; -template <> -struct has_function_signature : public std::true_type {}; -template <> -struct has_function_signature : public std::true_type { -}; -template <> -struct has_function_signature - : public std::true_type {}; - -template struct has_access : public std::false_type {}; -template <> struct has_access : public std::true_type {}; -template <> struct has_access : public std::true_type {}; -template <> struct has_access : public std::true_type {}; -template <> -struct has_access : public std::true_type {}; -template <> -struct has_access - : public std::true_type {}; -template <> -struct has_access : public std::true_type {}; -template <> struct has_access : public std::true_type {}; -template <> struct has_access : public std::true_type {}; -template <> -struct has_access : public std::true_type {}; -template <> -struct has_access - : public std::true_type {}; - -template struct has_template : public std::false_type {}; -template <> struct has_template : public std::true_type {}; -template <> -struct has_template - : public std::true_type {}; -template <> struct has_template : public std::true_type {}; -template <> -struct has_template : public std::true_type {}; -template <> -struct has_template - : public std::true_type {}; -template <> -struct has_template : public std::true_type {}; -template <> -struct has_template : public std::true_type {}; - -template <> -struct has_template : public std::true_type {}; -template <> -struct has_function_signature - : public std::true_type {}; -template <> -struct has_function_signature - : public std::true_type {}; - /// APISet holds the set of API records collected from given inputs. class APISet { public: - NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name, - StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeaderg); - /// Create and add a global variable record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - GlobalVariableRecord * - addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeadin, bool IsFromSystemHeaderg); + /// Get the target triple for the ExtractAPI invocation. + const llvm::Triple &getTarget() const { return Target; } - GlobalVariableTemplateRecord * - addGlobalVariableTemplate(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader); + /// Get the language used by the APIs. + Language getLanguage() const { return Lang; } - /// Create and add a function record into the API set. + /// Finds the APIRecord for a given USR. /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - GlobalFunctionRecord * - addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, - FunctionSignature Signature, bool IsFromSystemHeader); - - GlobalFunctionTemplateRecord *addGlobalFunctionTemplate( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - Template Template, bool IsFromSystemHeader); - - GlobalFunctionTemplateSpecializationRecord * - addGlobalFunctionTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - bool IsFromSystemHeader); + /// \returns a pointer to the APIRecord associated with that USR or nullptr. + APIRecord *findRecordForUSR(StringRef USR) const; - /// Create and add an enum constant record into the API set. + /// Copy \p String into the Allocator in this APISet. /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - EnumConstantRecord * - addEnumConstant(EnumRecord *Enum, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); + /// \returns a StringRef of the copied string in APISet::Allocator. + StringRef copyString(StringRef String); - /// Create and add an enum record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); + SymbolReference createSymbolReference(StringRef Name, StringRef USR, + StringRef Source = ""); - /// Create and add a record field record into the API set. + /// Create a subclass of \p APIRecord and store it in the APISet. /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - RecordFieldRecord * - addRecordField(RecordRecord *Record, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, APIRecord::RecordKind Kind, - bool IsFromSystemHeader); - - /// Create and add a record record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - RecordRecord *addRecord(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - APIRecord::RecordKind Kind, bool IsFromSystemHeader); - - StaticFieldRecord * - addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, SymbolReference Context, - AccessControl Access, bool IsFromSystemHeaderg); - - CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name, - StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - AccessControl Access, bool IsFromSystemHeader); - - CXXFieldTemplateRecord *addCXXFieldTemplate( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - AccessControl Access, Template Template, bool IsFromSystemHeader); - - CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - APIRecord::RecordKind Kind, AccessControl Access, - bool IsFromSystemHeader); - - ClassTemplateRecord * - addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - AccessControl Access, bool IsFromSystemHeader); - - ClassTemplateSpecializationRecord *addClassTemplateSpecialization( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - AccessControl Access, bool IsFromSystemHeader); - - ClassTemplatePartialSpecializationRecord * - addClassTemplatePartialSpecialization( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, AccessControl Access, bool IsFromSystemHeader); - - GlobalVariableTemplateSpecializationRecord * - addGlobalVariableTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); - - GlobalVariableTemplatePartialSpecializationRecord * - addGlobalVariableTemplatePartialSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader); - - CXXMethodRecord *addCXXInstanceMethod( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader); - - CXXMethodRecord *addCXXStaticMethod( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader); - - CXXMethodRecord *addCXXSpecialMethod( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader); - - CXXMethodTemplateRecord *addCXXMethodTemplate( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, Template Template, - bool IsFromSystemHeader); + /// \returns A pointer to the created record or the already existing record + /// matching this USR. + template + typename std::enable_if_t, RecordTy> * + createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); + + ArrayRef getTopLevelRecords() const { + return TopLevelRecords; + } - CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader); + APISet(const llvm::Triple &Target, Language Lang, + const std::string &ProductName) + : Target(Target), Lang(Lang), ProductName(ProductName) {} - ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader); + // Prevent moves and copies + APISet(const APISet &Other) = delete; + APISet &operator=(const APISet &Other) = delete; + APISet(APISet &&Other) = delete; + APISet &operator=(APISet &&Other) = delete; - /// Create and add an Objective-C category record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCCategoryRecord * - addObjCCategory(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, SymbolReference Interface, - bool IsFromSystemHeader, bool IsFromExternalModule); +private: + /// BumpPtrAllocator that serves as the memory arena for the allocated objects + llvm::BumpPtrAllocator Allocator; - /// Create and add an Objective-C interface record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCInterfaceRecord * - addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, SymbolReference SuperClass, - bool IsFromSystemHeader); + const llvm::Triple Target; + const Language Lang; - /// Create and add an Objective-C method record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCMethodRecord * - addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - bool IsInstanceMethod, bool IsFromSystemHeader); + struct APIRecordDeleter { + void operator()(APIRecord *Record) { Record->~APIRecord(); } + }; - /// Create and add an Objective-C property record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCPropertyRecord * - addObjCProperty(ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, - ObjCPropertyRecord::AttributeKind Attributes, - StringRef GetterName, StringRef SetterName, bool IsOptional, - bool IsInstanceProperty, bool IsFromSystemHeader); + // Ensure that the destructor of each record is called when the LookupTable is + // destroyed without calling delete operator as the memory for the record + // lives in the BumpPtrAllocator. + using APIRecordStoredPtr = std::unique_ptr; + llvm::DenseMap USRBasedLookupTable; + std::vector TopLevelRecords; - /// Create and add an Objective-C instance variable record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCInstanceVariableRecord *addObjCInstanceVariable( - ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - ObjCInstanceVariableRecord::AccessControl Access, - bool IsFromSystemHeader); +public: + const std::string ProductName; +}; - /// Create and add an Objective-C protocol record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - ObjCProtocolRecord * - addObjCProtocol(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); +template +typename std::enable_if_t, RecordTy> * +APISet::createRecord(StringRef USR, StringRef Name, + CtorArgsContTy &&...CtorArgs) { + // Ensure USR refers to a String stored in the allocator. + auto USRString = copyString(USR); + auto Result = USRBasedLookupTable.insert({USRString, nullptr}); + RecordTy *Record; + + // Create the record if it does not already exist + if (Result.second) { + Record = new (Allocator) RecordTy( + USRString, copyString(Name), std::forward(CtorArgs)...); + // Store the record in the record lookup map + Result.first->second = APIRecordStoredPtr(Record); + + if (auto *ParentContext = + dyn_cast_if_present(Record->Parent.Record)) + ParentContext->addToRecordChain(Record); + else + TopLevelRecords.push_back(Record); + } else { + Record = dyn_cast(Result.first->second.get()); + } - /// Create a macro definition record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSRForMacro(StringRef Name, - /// SourceLocation SL, const SourceManager &SM) is a helper method to generate - /// the USR for the macro and keep it alive in APISet. - MacroDefinitionRecord *addMacroDefinition(StringRef Name, StringRef USR, - PresumedLoc Loc, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader); - - /// Create a typedef record into the API set. - /// - /// Note: the caller is responsible for keeping the StringRef \p Name and - /// \p USR alive. APISet::copyString provides a way to copy strings into - /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method - /// to generate the USR for \c D and keep it alive in APISet. - TypedefRecord * - addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - SymbolReference UnderlyingType, bool IsFromSystemHeader); - - /// A mapping type to store a set of APIRecord%s with the USR as the key. - template ::value>> - using RecordMap = llvm::MapVector>; + return Record; +} - /// Get the target triple for the ExtractAPI invocation. - const llvm::Triple &getTarget() const { return Target; } +// Helper type for implementing casting to RecordContext pointers. +// Selected when FromTy not a known subclass of RecordContext. +template > +struct ToRecordContextCastInfoWrapper { + static_assert(std::is_base_of_v, + "Can only cast APIRecord and derived classes to RecordContext"); - /// Get the language used by the APIs. - Language getLanguage() const { return Lang; } + static bool isPossible(FromTy *From) { return RecordContext::classof(From); } - const RecordMap &getNamespaces() const { return Namespaces; } - const RecordMap &getGlobalFunctions() const { - return GlobalFunctions; - } - const RecordMap & - getGlobalFunctionTemplates() const { - return GlobalFunctionTemplates; - } - const RecordMap & - getGlobalFunctionTemplateSpecializations() const { - return GlobalFunctionTemplateSpecializations; - } - const RecordMap &getGlobalVariables() const { - return GlobalVariables; - } - const RecordMap & - getGlobalVariableTemplates() const { - return GlobalVariableTemplates; + static RecordContext *doCast(FromTy *From) { + return APIRecord::castToRecordContext(From); } - const RecordMap &getStaticFields() const { - return StaticFields; - } - const RecordMap & - getGlobalVariableTemplateSpecializations() const { - return GlobalVariableTemplateSpecializations; - } - const RecordMap & - getGlobalVariableTemplatePartialSpecializations() const { - return GlobalVariableTemplatePartialSpecializations; - } - const RecordMap &getEnums() const { return Enums; } - const RecordMap &getRecords() const { return Records; } - const RecordMap &getCXXClasses() const { return CXXClasses; } - const RecordMap &getCXXMethodTemplates() const { - return CXXMethodTemplates; - } - const RecordMap &getCXXInstanceMethods() const { - return CXXInstanceMethods; - } - const RecordMap &getCXXStaticMethods() const { - return CXXStaticMethods; - } - const RecordMap &getCXXFields() const { return CXXFields; } - const RecordMap & - getCXXMethodTemplateSpecializations() const { - return CXXMethodTemplateSpecializations; - } - const RecordMap &getCXXFieldTemplates() const { - return CXXFieldTemplates; - } - const RecordMap &getClassTemplates() const { - return ClassTemplates; - } - const RecordMap & - getClassTemplateSpecializations() const { - return ClassTemplateSpecializations; +}; + +// Selected when FromTy is a known subclass of RecordContext. +template struct ToRecordContextCastInfoWrapper { + static_assert(std::is_base_of_v, + "Can only cast APIRecord and derived classes to RecordContext"); + static bool isPossible(const FromTy *From) { return true; } + static RecordContext *doCast(FromTy *From) { + return static_cast(From); } - const RecordMap & - getClassTemplatePartialSpecializations() const { - return ClassTemplatePartialSpecializations; +}; + +// Helper type for implementing casting to RecordContext pointers. +// Selected when ToTy isn't a known subclass of RecordContext +template > +struct FromRecordContextCastInfoWrapper { + static_assert( + std::is_base_of_v, + "Can only class RecordContext to APIRecord and derived classes"); + + static bool isPossible(RecordContext *Ctx) { + return ToTy::classofKind(Ctx->getKind()); } - const RecordMap &getConcepts() const { return Concepts; } - const RecordMap &getObjCCategories() const { - return ObjCCategories; + + static ToTy *doCast(RecordContext *Ctx) { + return APIRecord::castFromRecordContext(Ctx); } - const RecordMap &getObjCInterfaces() const { - return ObjCInterfaces; +}; + +// Selected when ToTy is a known subclass of RecordContext. +template struct FromRecordContextCastInfoWrapper { + static_assert( + std::is_base_of_v, + "Can only class RecordContext to APIRecord and derived classes"); + static bool isPossible(RecordContext *Ctx) { + return ToTy::classof(Ctx->getKind()); } - const RecordMap &getObjCProtocols() const { - return ObjCProtocols; + static RecordContext *doCast(RecordContext *Ctx) { + return static_cast(Ctx); } - const RecordMap &getMacros() const { return Macros; } - const RecordMap &getTypedefs() const { return Typedefs; } - - /// Finds the APIRecord for a given USR. - /// - /// \returns a pointer to the APIRecord associated with that USR or nullptr. - APIRecord *findRecordForUSR(StringRef USR) const; - - /// Generate and store the USR of declaration \p D. - /// - /// Note: The USR string is stored in and owned by Allocator. - /// - /// \returns a StringRef of the generated USR string. - StringRef recordUSR(const Decl *D); - - /// Generate and store the USR for a macro \p Name. - /// - /// Note: The USR string is stored in and owned by Allocator. - /// - /// \returns a StringRef to the generate USR string. - StringRef recordUSRForMacro(StringRef Name, SourceLocation SL, - const SourceManager &SM); - - /// Copy \p String into the Allocator in this APISet. - /// - /// \returns a StringRef of the copied string in APISet::Allocator. - StringRef copyString(StringRef String); +}; - APISet(const llvm::Triple &Target, Language Lang, - const std::string &ProductName) - : Target(Target), Lang(Lang), ProductName(ProductName) {} +} // namespace extractapi +} // namespace clang -private: - /// BumpPtrAllocator to store generated/copied strings. - /// - /// Note: The main use for this is being able to deduplicate strings. - llvm::BumpPtrAllocator StringAllocator; +// Implement APIRecord (and derived classes) to and from RecordContext +// conversions +namespace llvm { + +template +struct CastInfo<::clang::extractapi::RecordContext, FromTy *> + : public NullableValueCastFailed<::clang::extractapi::RecordContext *>, + public DefaultDoCastIfPossible< + ::clang::extractapi::RecordContext *, FromTy *, + CastInfo<::clang::extractapi::RecordContext, FromTy *>> { + static inline bool isPossible(FromTy *From) { + return ::clang::extractapi::ToRecordContextCastInfoWrapper< + FromTy>::isPossible(From); + } - const llvm::Triple Target; - const Language Lang; + static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) { + return ::clang::extractapi::ToRecordContextCastInfoWrapper::doCast( + From); + } +}; - llvm::DenseMap USRBasedLookupTable; - RecordMap Namespaces; - RecordMap GlobalFunctions; - RecordMap GlobalFunctionTemplates; - RecordMap - GlobalFunctionTemplateSpecializations; - RecordMap GlobalVariables; - RecordMap GlobalVariableTemplates; - RecordMap - GlobalVariableTemplateSpecializations; - RecordMap - GlobalVariableTemplatePartialSpecializations; - RecordMap Concepts; - RecordMap StaticFields; - RecordMap Enums; - RecordMap Records; - RecordMap CXXClasses; - RecordMap CXXFields; - RecordMap CXXMethods; - RecordMap CXXInstanceMethods; - RecordMap CXXStaticMethods; - RecordMap CXXMethodTemplates; - RecordMap - CXXMethodTemplateSpecializations; - RecordMap CXXFieldTemplates; - RecordMap ClassTemplates; - RecordMap ClassTemplateSpecializations; - RecordMap - ClassTemplatePartialSpecializations; - RecordMap ObjCCategories; - RecordMap ObjCInterfaces; - RecordMap ObjCProtocols; - RecordMap Macros; - RecordMap Typedefs; +template +struct CastInfo<::clang::extractapi::RecordContext, const FromTy *> + : public ConstStrippingForwardingCast< + ::clang::extractapi::RecordContext, const FromTy *, + CastInfo<::clang::extractapi::RecordContext, FromTy *>> {}; + +template +struct CastInfo + : public NullableValueCastFailed, + public DefaultDoCastIfPossible< + ToTy *, ::clang::extractapi::RecordContext *, + CastInfo> { + static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) { + return ::clang::extractapi::FromRecordContextCastInfoWrapper< + ToTy>::isPossible(Ctx); + } -public: - const std::string ProductName; + static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) { + return ::clang::extractapi::FromRecordContextCastInfoWrapper::doCast( + Ctx); + } }; -} // namespace extractapi -} // namespace clang +template +struct CastInfo + : public ConstStrippingForwardingCast< + ToTy, const ::clang::extractapi::RecordContext *, + CastInfo> {}; + +} // namespace llvm #endif // LLVM_CLANG_EXTRACTAPI_API_H diff --git a/clang/include/clang/ExtractAPI/APIRecords.inc b/clang/include/clang/ExtractAPI/APIRecords.inc new file mode 100644 index 00000000000000..15fee809656d9a --- /dev/null +++ b/clang/include/clang/ExtractAPI/APIRecords.inc @@ -0,0 +1,103 @@ +//===- ExtractAPI/APIRecords.inc --------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the classes defined from ExtractAPI's APIRecord +/// +//===----------------------------------------------------------------------===// + +#ifndef ABSTRACT_RECORD +#define ABSTRACT_RECORD(CLASS, BASE) RECORD(CLASS, BASE) +#endif +#ifndef CONCRETE_RECORD +#define CONCRETE_RECORD(CLASS, BASE, KIND) RECORD(CLASS, BASE) +#endif +#ifndef RECORD +#define RECORD(CLASS, BASE) +#endif + +CONCRETE_RECORD(NamespaceRecord, APIRecord, RK_Namespace) +CONCRETE_RECORD(GlobalFunctionRecord, APIRecord, RK_GlobalFunction) +CONCRETE_RECORD(GlobalFunctionTemplateRecord, GlobalFunctionRecord, + RK_GlobalFunctionTemplate) +CONCRETE_RECORD(GlobalFunctionTemplateSpecializationRecord, + GlobalFunctionRecord, RK_GlobalFunctionTemplateSpecialization) +CONCRETE_RECORD(GlobalVariableRecord, APIRecord, RK_GlobalVariable) +CONCRETE_RECORD(GlobalVariableTemplateRecord, GlobalVariableRecord, + RK_GlobalVariableTemplate) +CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord, + GlobalVariableRecord, RK_GlobalVariableTemplateSpecialization) +CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord, + GlobalVariableRecord, + RK_GlobalVariableTemplatePartialSpecialization) +CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant) +CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum) +ABSTRACT_RECORD(RecordFieldRecord, APIRecord) +ABSTRACT_RECORD(RecordRecord, APIRecord) +CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField) +CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct) +CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField) +CONCRETE_RECORD(UnionRecord, APIRecord, RK_Union) +CONCRETE_RECORD(CXXFieldRecord, APIRecord, RK_CXXField) +CONCRETE_RECORD(CXXFieldTemplateRecord, CXXFieldRecord, RK_CXXFieldTemplate) +ABSTRACT_RECORD(CXXMethodRecord, APIRecord) +CONCRETE_RECORD(CXXConstructorRecord, CXXMethodRecord, RK_CXXConstructorMethod) +CONCRETE_RECORD(CXXDestructorRecord, CXXMethodRecord, RK_CXXDestructorMethod) +CONCRETE_RECORD(CXXStaticMethodRecord, CXXMethodRecord, RK_CXXStaticMethod) +CONCRETE_RECORD(CXXInstanceMethodRecord, CXXMethodRecord, RK_CXXInstanceMethod) +CONCRETE_RECORD(CXXMethodTemplateRecord, CXXMethodRecord, RK_CXXMethodTemplate) +CONCRETE_RECORD(CXXMethodTemplateSpecializationRecord, CXXMethodRecord, + RK_CXXMethodTemplateSpecialization) +ABSTRACT_RECORD(ObjCPropertyRecord, APIRecord) +CONCRETE_RECORD(ObjCInstancePropertyRecord, ObjCPropertyRecord, + RK_ObjCInstanceProperty) +CONCRETE_RECORD(ObjCClassPropertyRecord, ObjCPropertyRecord, + RK_ObjCClassProperty) +CONCRETE_RECORD(ObjCInstanceVariableRecord, APIRecord, RK_ObjCIvar) +ABSTRACT_RECORD(ObjCMethodRecord, APIRecord) +CONCRETE_RECORD(ObjCInstanceMethodRecord, ObjCMethodRecord, + RK_ObjCInstanceMethod) +CONCRETE_RECORD(ObjCClassMethodRecord, ObjCMethodRecord, RK_ObjCClassMethod) +CONCRETE_RECORD(StaticFieldRecord, CXXFieldRecord, RK_StaticField) +ABSTRACT_RECORD(ObjCContainerRecord, APIRecord) +CONCRETE_RECORD(CXXClassRecord, APIRecord, RK_CXXClass) +CONCRETE_RECORD(ClassTemplateRecord, CXXClassRecord, RK_ClassTemplate) +CONCRETE_RECORD(ClassTemplateSpecializationRecord, CXXClassRecord, + RK_ClassTemplateSpecialization) +CONCRETE_RECORD(ClassTemplatePartialSpecializationRecord, CXXClassRecord, + RK_ClassTemplatePartialSpecialization) +CONCRETE_RECORD(ConceptRecord, APIRecord, RK_Concept) +CONCRETE_RECORD(ObjCCategoryRecord, ObjCContainerRecord, RK_ObjCCategory) +CONCRETE_RECORD(ObjCInterfaceRecord, ObjCContainerRecord, RK_ObjCInterface) +CONCRETE_RECORD(ObjCProtocolRecord, ObjCContainerRecord, RK_ObjCProtocol) +CONCRETE_RECORD(MacroDefinitionRecord, APIRecord, RK_MacroDefinition) +CONCRETE_RECORD(TypedefRecord, APIRecord, RK_Typedef) + +#undef CONCRETE_RECORD +#undef ABSTRACT_RECORD +#undef RECORD + +#ifndef RECORD_CONTEXT +#define RECORD_CONTEXT(CLASS, KIND) +#endif + +RECORD_CONTEXT(NamespaceRecord, RK_Namespace) +RECORD_CONTEXT(EnumRecord, RK_Enum) +RECORD_CONTEXT(StructRecord, RK_Struct) +RECORD_CONTEXT(UnionRecord, RK_Union) +RECORD_CONTEXT(ObjCCategoryRecord, RK_ObjCCategory) +RECORD_CONTEXT(ObjCInterfaceRecord, RK_ObjCInterface) +RECORD_CONTEXT(ObjCProtocolRecord, RK_ObjCProtocol) +RECORD_CONTEXT(CXXClassRecord, RK_CXXClass) +RECORD_CONTEXT(ClassTemplateRecord, RK_ClassTemplate) +RECORD_CONTEXT(ClassTemplateSpecializationRecord, + RK_ClassTemplateSpecialization) +RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord, + RK_ClassTemplatePartialSpecialization) + +#undef RECORD_CONTEXT diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index b85a5d21d61217..94392c18516595 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -27,8 +27,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/MacroInfo.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include namespace clang { @@ -182,6 +180,18 @@ class DeclarationFragments { /// appending to chain up consecutive appends. DeclarationFragments &appendSpace(); + /// Append a text Fragment of a semicolon character. + /// + /// \returns a reference to the DeclarationFragments object itself after + /// appending to chain up consecutive appends. + DeclarationFragments &appendSemicolon(); + + /// Removes a trailing semicolon character if present. + /// + /// \returns a reference to the DeclarationFragments object itself after + /// removing to chain up consecutive operations. + DeclarationFragments &removeTrailingSemicolon(); + /// Get the string description of a FragmentKind \p Kind. static StringRef getFragmentKindString(FragmentKind Kind); @@ -194,12 +204,14 @@ class DeclarationFragments { static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl); private: + DeclarationFragments &appendUnduplicatedTextCharacter(char Character); std::vector Fragments; }; class AccessControl { public: AccessControl(std::string Access) : Access(Access) {} + AccessControl() : Access("public") {} const std::string &getAccess() const { return Access; } @@ -315,13 +327,9 @@ class DeclarationFragmentsBuilder { static DeclarationFragments getFragmentsForTemplateParameters(ArrayRef); - static std::string - getNameForTemplateArgument(const ArrayRef, std::string); - - static DeclarationFragments - getFragmentsForTemplateArguments(const ArrayRef, - ASTContext &, - const std::optional>); + static DeclarationFragments getFragmentsForTemplateArguments( + const ArrayRef, ASTContext &, + const std::optional>); static DeclarationFragments getFragmentsForConcept(const ConceptDecl *); @@ -430,12 +438,7 @@ DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { if (isa(Function) && dyn_cast(Function)->getDescribedFunctionTemplate() && StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) { - std::string ProperArgName = - getNameForTemplateArgument(dyn_cast(Function) - ->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - ReturnType.begin()->Spelling); + std::string ProperArgName = Function->getReturnType().getAsString(); ReturnType.begin()->Spelling.swap(ProperArgName); } ReturnType.append(std::move(After)); diff --git a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h index ac4f391db5f14a..08210a7ee05954 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h @@ -17,6 +17,8 @@ #include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/APIIgnoresList.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/raw_ostream.h" namespace clang { @@ -29,8 +31,8 @@ class ExtractAPIActionBase { /// A representation of the APIs this action extracts. std::unique_ptr API; - /// A stream to the output file of this action. - std::unique_ptr OS; + /// A stream to the main output file of this action. + std::unique_ptr OS; /// The product this action is extracting API information for. std::string ProductName; @@ -46,7 +48,7 @@ class ExtractAPIActionBase { /// /// Use the serializer to generate output symbol graph files from /// the information gathered during the execution of Action. - void ImplEndSourceFileAction(); + void ImplEndSourceFileAction(CompilerInstance &CI); }; } // namespace clang diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index e1c3e41c750d40..4cb866892b5d00 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -14,23 +14,23 @@ #ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H #define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H -#include "clang/AST/Availability.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/Specifiers.h" -#include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/FunctionExtras.h" - -#include "clang/AST/ASTContext.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/API.h" +#include "clang/ExtractAPI/DeclarationFragments.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include namespace clang { @@ -130,12 +130,6 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { void recordEnumConstants(EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants); - /// Collect API information for the record fields and associate with the - /// parent struct. - void recordRecordFields(RecordRecord *RecordRecord, - APIRecord::RecordKind FieldKind, - const RecordDecl::field_range Fields); - /// Collect API information for the Objective-C methods and associate with the /// parent container. void recordObjCMethods(ObjCContainerRecord *Container, @@ -172,6 +166,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { return *static_cast(this); } +protected: SmallVector getBases(const CXXRecordDecl *Decl) { // FIXME: store AccessSpecifier given by inheritance SmallVector Bases; @@ -182,49 +177,54 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { SymbolReference BaseClass; if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) { BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString()); - BaseClass.USR = API.recordUSR( - BaseSpecifier.getType()->getAs()->getDecl()); + if (auto *TTPTD = BaseSpecifier.getType() + ->getAs() + ->getDecl()) { + SmallString<128> USR; + index::generateUSRForDecl(TTPTD, USR); + BaseClass.USR = API.copyString(USR); + BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD)); + } } else { - CXXRecordDecl *BaseClassDecl = - BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl(); - BaseClass.Name = BaseClassDecl->getName(); - BaseClass.USR = API.recordUSR(BaseClassDecl); + BaseClass = createSymbolReferenceForDecl( + *BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl()); } Bases.emplace_back(BaseClass); } return Bases; } - APIRecord *determineParentRecord(const DeclContext *Context) { - SmallString<128> ParentUSR; - if (Context->getDeclKind() == Decl::TranslationUnit) - return nullptr; + StringRef getOwningModuleName(const Decl &D) { + if (auto *OwningModule = D.getImportedOwningModule()) + return OwningModule->Name; - index::generateUSRForDecl(dyn_cast(Context), ParentUSR); + return {}; + } - APIRecord *Parent = API.findRecordForUSR(ParentUSR); - return Parent; + SymbolReference createHierarchyInformationForDecl(const Decl &D) { + const auto *Context = cast_if_present(D.getDeclContext()); + + if (!Context || isa(Context)) + return {}; + + return createSymbolReferenceForDecl(*Context); } -}; -template -static void modifyRecords(const T &Records, const StringRef &Name) { - for (const auto &Record : Records) { - if (Name == Record.second.get()->Name) { - auto &DeclFragment = Record.second->Declaration; - DeclFragment.insert(DeclFragment.begin(), " ", - DeclarationFragments::FragmentKind::Text); - DeclFragment.insert(DeclFragment.begin(), "typedef", - DeclarationFragments::FragmentKind::Keyword, "", - nullptr); - DeclFragment.insert(--DeclFragment.end(), " { ... } ", - DeclarationFragments::FragmentKind::Text); - DeclFragment.insert(--DeclFragment.end(), Name, - DeclarationFragments::FragmentKind::Identifier); - break; - } + SymbolReference createSymbolReferenceForDecl(const Decl &D) { + SmallString<128> USR; + index::generateUSRForDecl(&D, USR); + + APIRecord *Record = API.findRecordForUSR(USR); + if (Record) + return SymbolReference(Record); + + StringRef Name; + if (auto *ND = dyn_cast(&D)) + Name = ND->getName(); + + return API.createSymbolReference(Name, USR, getOwningModuleName(D)); } -} +}; template bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) { @@ -251,7 +251,8 @@ bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) { // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -267,21 +268,17 @@ bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) { DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); if (Decl->isStaticDataMember()) { - SymbolReference Context; - // getDeclContext() should return a RecordDecl since we - // are currently handling a static data member. - auto *Record = cast(Decl->getDeclContext()); - Context.Name = Record->getName(); - Context.USR = API.recordUSR(Record); auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - API.addStaticField(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Linkage, Comment, Declaration, SubHeading, Context, - Access, isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, Access, isInSystemHeader(Decl)); } else // Add the global variable record to the API set. - API.addGlobalVar(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Linkage, Comment, Declaration, SubHeading, - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); return true; } @@ -304,7 +301,7 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl( return true; } - // Skip templated functions. + // Skip templated functions that aren't processed here. switch (Decl->getTemplatedKind()) { case FunctionDecl::TK_NonTemplate: case FunctionDecl::TK_DependentNonTemplate: @@ -321,7 +318,8 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -337,18 +335,19 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl( FunctionSignature Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); if (Decl->getTemplateSpecializationInfo()) - API.addGlobalFunctionTemplateSpecialization( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, - Comment, + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, DeclarationFragmentsBuilder:: getFragmentsForFunctionTemplateSpecialization(Decl), SubHeading, Signature, isInSystemHeader(Decl)); else // Add the function record to the API set. - API.addGlobalFunction( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, - Comment, DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), - SubHeading, Signature, isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, + DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading, + Signature, isInSystemHeader(Decl)); return true; } @@ -368,7 +367,8 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { Name = QualifiedNameBuffer.str(); } - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -382,13 +382,13 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - EnumRecord *EnumRecord = API.addEnum( - API.copyString(Name), USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Comment, Declaration, SubHeading, isInSystemHeader(Decl)); + auto *ER = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + isInSystemHeader(Decl)); // Now collect information about the enumerators in this enum. - getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord, - Decl->enumerators()); + getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators()); return true; } @@ -476,13 +476,13 @@ bool ExtractAPIVisitorBase::WalkUpFromNamespaceDecl( template bool ExtractAPIVisitorBase::VisitNamespaceDecl( const NamespaceDecl *Decl) { - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; if (Decl->isAnonymousNamespace()) return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); @@ -497,10 +497,10 @@ bool ExtractAPIVisitorBase::VisitNamespaceDecl( DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); - API.addNamespace(Parent, Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, - Declaration, SubHeading, isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); return true; } @@ -509,14 +509,20 @@ template bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) { if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; + + SmallString<128> QualifiedNameBuffer; // Collect symbol information. StringRef Name = Decl->getName(); if (Name.empty()) Name = getTypedefName(Decl); - if (Name.empty()) - return true; + if (Name.empty()) { + llvm::raw_svector_ostream OS(QualifiedNameBuffer); + Decl->printQualifiedName(OS); + Name = QualifiedNameBuffer.str(); + } - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -531,21 +537,16 @@ bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) { DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - auto RecordKind = APIRecord::RK_Struct; - auto FieldRecordKind = APIRecord::RK_StructField; - - if (Decl->isUnion()) { - RecordKind = APIRecord::RK_Union; - FieldRecordKind = APIRecord::RK_UnionField; - } - - RecordRecord *RecordRecord = API.addRecord( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, RecordKind, isInSystemHeader(Decl)); - - // Now collect information about the fields in this struct. - getDerivedExtractAPIVisitor().recordRecordFields( - RecordRecord, FieldRecordKind, Decl->fields()); + if (Decl->isUnion()) + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); + else + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); return true; } @@ -558,7 +559,8 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -580,24 +582,25 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( Kind = APIRecord::RecordKind::RK_CXXClass; auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); - CXXClassRecord *CXXClassRecord; + CXXClassRecord *Record; if (Decl->getDescribedClassTemplate()) { // Inject template fragments before class fragments. Declaration.insert( Declaration.begin(), DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( Decl->getDescribedClassTemplate())); - CXXClassRecord = API.addClassTemplate( - Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()), - Access, isInSystemHeader(Decl)); + Record = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, Template(Decl->getDescribedClassTemplate()), Access, + isInSystemHeader(Decl)); } else - CXXClassRecord = API.addCXXClass( - Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Kind, Access, isInSystemHeader(Decl)); + Record = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, Kind, Access, isInSystemHeader(Decl)); - CXXClassRecord->Bases = getBases(Decl); + Record->Bases = getBases(Decl); return true; } @@ -614,7 +617,8 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( if (isa(Decl) || isa(Decl)) return true; - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -627,14 +631,10 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); - auto *Parent = API.findRecordForUSR(ParentUSR); - if (Decl->isTemplated()) { - FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate(); - API.addCXXMethodTemplate( - API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc, + if (FunctionTemplateDecl *TemplateDecl = + Decl->getDescribedFunctionTemplate()) { + API.createRecord( + USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( TemplateDecl), @@ -642,27 +642,27 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( DeclarationFragmentsBuilder::getAccessControl(TemplateDecl), Template(TemplateDecl), isInSystemHeader(Decl)); } else if (Decl->getTemplateSpecializationInfo()) - API.addCXXMethodTemplateSpec( - Parent, Decl->getName(), USR, Loc, + API.createRecord( + USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder:: getFragmentsForFunctionTemplateSpecialization(Decl), SubHeading, Signature, Access, isInSystemHeader(Decl)); else if (Decl->isOverloadedOperator()) - API.addCXXInstanceMethod( - Parent, API.copyString(Decl->getNameAsString()), USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, + API.createRecord( + USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), + Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl), SubHeading, Signature, Access, isInSystemHeader(Decl)); else if (Decl->isStatic()) - API.addCXXStaticMethod( - Parent, Decl->getName(), USR, Loc, + API.createRecord( + USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, Signature, Access, isInSystemHeader(Decl)); else - API.addCXXInstanceMethod( - Parent, Decl->getName(), USR, Loc, + API.createRecord( + USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, Signature, Access, isInSystemHeader(Decl)); @@ -673,9 +673,13 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( template bool ExtractAPIVisitorBase::VisitCXXConstructorDecl( const CXXConstructorDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || + Decl->isImplicit()) + return true; - StringRef Name = API.copyString(Decl->getNameAsString()); - StringRef USR = API.recordUSR(Decl); + auto Name = Decl->getNameAsString(); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -692,22 +696,24 @@ bool ExtractAPIVisitorBase::VisitCXXConstructorDecl( FunctionSignature Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); - API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Signature, Access, - isInSystemHeader(Decl)); + + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + Signature, Access, isInSystemHeader(Decl)); return true; } template bool ExtractAPIVisitorBase::VisitCXXDestructorDecl( const CXXDestructorDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || + Decl->isImplicit()) + return true; - StringRef Name = API.copyString(Decl->getNameAsString()); - StringRef USR = API.recordUSR(Decl); + auto Name = Decl->getNameAsString(); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -724,13 +730,10 @@ bool ExtractAPIVisitorBase::VisitCXXDestructorDecl( FunctionSignature Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); - API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Signature, Access, - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + Signature, Access, isInSystemHeader(Decl)); return true; } @@ -740,7 +743,8 @@ bool ExtractAPIVisitorBase::VisitConceptDecl(const ConceptDecl *Decl) { return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -752,9 +756,10 @@ bool ExtractAPIVisitorBase::VisitConceptDecl(const ConceptDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForConcept(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - API.addConcept(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Comment, Declaration, SubHeading, Template(Decl), - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + Template(Decl), isInSystemHeader(Decl)); return true; } @@ -765,7 +770,8 @@ bool ExtractAPIVisitorBase::VisitClassTemplateSpecializationDecl( return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -779,14 +785,13 @@ bool ExtractAPIVisitorBase::VisitClassTemplateSpecializationDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); - auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization( - Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, + auto *CTSR = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl), isInSystemHeader(Decl)); - ClassTemplateSpecializationRecord->Bases = getBases(Decl); + CTSR->Bases = getBases(Decl); return true; } @@ -799,7 +804,8 @@ bool ExtractAPIVisitorBase:: return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -811,15 +817,13 @@ bool ExtractAPIVisitorBase:: getFragmentsForClassTemplatePartialSpecialization(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); - auto *ClassTemplatePartialSpecRecord = - API.addClassTemplatePartialSpecialization( - Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Comment, Declaration, SubHeading, Template(Decl), - DeclarationFragmentsBuilder::getAccessControl(Decl), - isInSystemHeader(Decl)); + auto *CTPSR = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl), + isInSystemHeader(Decl)); - ClassTemplatePartialSpecRecord->Bases = getBases(Decl); + CTPSR->Bases = getBases(Decl); return true; } @@ -832,7 +836,8 @@ bool ExtractAPIVisitorBase::VisitVarTemplateDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -853,20 +858,17 @@ bool ExtractAPIVisitorBase::VisitVarTemplateDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord) - API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, - DeclarationFragmentsBuilder::getAccessControl(Decl), - Template(Decl), isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl), + Template(Decl), isInSystemHeader(Decl)); else - API.addGlobalVariableTemplate(Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), - Linkage, Comment, Declaration, SubHeading, - Template(Decl), isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, Template(Decl), isInSystemHeader(Decl)); return true; } @@ -878,7 +880,8 @@ bool ExtractAPIVisitorBase::VisitVarTemplateSpecializationDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -894,9 +897,10 @@ bool ExtractAPIVisitorBase::VisitVarTemplateSpecializationDecl( Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - API.addGlobalVariableTemplateSpecialization( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, - Declaration, SubHeading, isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); return true; } @@ -908,7 +912,8 @@ bool ExtractAPIVisitorBase::VisitVarTemplatePartialSpecializationDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -923,9 +928,10 @@ bool ExtractAPIVisitorBase::VisitVarTemplatePartialSpecializationDecl( getFragmentsForVarTemplatePartialSpecialization(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - API.addGlobalVariableTemplatePartialSpecialization( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, - Declaration, SubHeading, Template(Decl), isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, Template(Decl), isInSystemHeader(Decl)); return true; } @@ -939,7 +945,8 @@ bool ExtractAPIVisitorBase::VisitFunctionTemplateDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -954,8 +961,9 @@ bool ExtractAPIVisitorBase::VisitFunctionTemplateDecl( FunctionSignature Signature = DeclarationFragmentsBuilder::getFunctionSignature( Decl->getTemplatedDecl()); - API.addGlobalFunctionTemplate( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl), SubHeading, Signature, Template(Decl), isInSystemHeader(Decl)); @@ -970,7 +978,8 @@ bool ExtractAPIVisitorBase::VisitObjCInterfaceDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); LinkageInfo Linkage = Decl->getLinkageAndVisibility(); @@ -988,24 +997,23 @@ bool ExtractAPIVisitorBase::VisitObjCInterfaceDecl( // Collect super class information. SymbolReference SuperClass; - if (const auto *SuperClassDecl = Decl->getSuperClass()) { - SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString(); - SuperClass.USR = API.recordUSR(SuperClassDecl); - } + if (const auto *SuperClassDecl = Decl->getSuperClass()) + SuperClass = createSymbolReferenceForDecl(*SuperClassDecl); - ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, - Declaration, SubHeading, SuperClass, isInSystemHeader(Decl)); + auto *InterfaceRecord = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, + SubHeading, SuperClass, isInSystemHeader(Decl)); // Record all methods (selectors). This doesn't include automatically // synthesized property methods. - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord, + getDerivedExtractAPIVisitor().recordObjCMethods(InterfaceRecord, Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord, + getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord, Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord, + getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord, Decl->ivars()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord, + getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord, Decl->protocols()); return true; @@ -1019,7 +1027,8 @@ bool ExtractAPIVisitorBase::VisitObjCProtocolDecl( // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -1034,15 +1043,15 @@ bool ExtractAPIVisitorBase::VisitObjCProtocolDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, isInSystemHeader(Decl)); + auto *ProtoRecord = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + isInSystemHeader(Decl)); - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord, - Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord, + getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods()); + getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord, Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord, + getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord, Decl->protocols()); return true; @@ -1061,25 +1070,36 @@ bool ExtractAPIVisitorBase::VisitTypedefNameDecl( if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; - // Add the notion of typedef for tag type (struct or enum) of the same name. - if (const ElaboratedType *ET = - dyn_cast(Decl->getUnderlyingType())) { - if (const TagType *TagTy = dyn_cast(ET->desugar())) { - if (Decl->getName() == TagTy->getDecl()->getName()) { - if (isa(TagTy->getDecl())) { - modifyRecords(API.getRecords(), Decl->getName()); - } - if (TagTy->getDecl()->isEnum()) { - modifyRecords(API.getEnums(), Decl->getName()); - } + StringRef Name = Decl->getName(); + + // If the underlying type was defined as part of the typedef modify it's + // fragments directly and pretend the typedef doesn't exist. + if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) { + if (TagDecl->getName() == Decl->getName() && + TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) { + SmallString<128> TagUSR; + index::generateUSRForDecl(TagDecl, TagUSR); + if (auto *Record = API.findRecordForUSR(TagUSR)) { + DeclarationFragments LeadingFragments; + LeadingFragments.append("typedef", + DeclarationFragments::FragmentKind::Keyword, "", + nullptr); + LeadingFragments.appendSpace(); + Record->Declaration.removeTrailingSemicolon() + .insert(Record->Declaration.begin(), std::move(LeadingFragments)) + .append(" { ... } ", DeclarationFragments::FragmentKind::Text) + .append(Name, DeclarationFragments::FragmentKind::Identifier) + .appendSemicolon(); + + return true; } } } PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); - StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); DocComment Comment; if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) @@ -1091,11 +1111,12 @@ bool ExtractAPIVisitorBase::VisitTypedefNameDecl( TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type, API); - API.addTypedef(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), - Comment, - DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl), - DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef, - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, + DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl), + DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef, + isInSystemHeader(Decl)); return true; } @@ -1107,7 +1128,8 @@ bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( return true; StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -1122,29 +1144,20 @@ bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( DeclarationFragmentsBuilder::getSubHeading(Decl); const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface(); - SymbolReference Interface(InterfaceDecl->getName(), - API.recordUSR(InterfaceDecl)); - - bool IsFromExternalModule = true; - for (const auto &Interface : API.getObjCInterfaces()) { - if (InterfaceDecl->getName() == Interface.second.get()->Name) { - IsFromExternalModule = false; - break; - } - } + SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl); - ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory( - Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Interface, isInSystemHeader(Decl), - IsFromExternalModule); + auto *CategoryRecord = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, + Interface, isInSystemHeader(Decl)); - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord, + getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord, Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord, + getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord, Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord, + getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord, Decl->ivars()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord, + getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord, Decl->protocols()); return true; @@ -1158,7 +1171,8 @@ void ExtractAPIVisitorBase::recordEnumConstants( for (const auto *Constant : Constants) { // Collect symbol information. StringRef Name = Constant->getName(); - StringRef USR = API.recordUSR(Constant); + SmallString<128> USR; + index::generateUSRForDecl(Constant, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Constant->getLocation()); DocComment Comment; @@ -1173,51 +1187,26 @@ void ExtractAPIVisitorBase::recordEnumConstants( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Constant); - API.addEnumConstant(EnumRecord, Name, USR, Loc, - AvailabilityInfo::createFromDecl(Constant), Comment, - Declaration, SubHeading, isInSystemHeader(Constant)); - } -} - -/// Collect API information for the struct fields and associate with the -/// parent struct. -template -void ExtractAPIVisitorBase::recordRecordFields( - RecordRecord *RecordRecord, APIRecord::RecordKind FieldKind, - const RecordDecl::field_range Fields) { - for (const auto *Field : Fields) { - // Collect symbol information. - StringRef Name = Field->getName(); - StringRef USR = API.recordUSR(Field); - PresumedLoc Loc = - Context.getSourceManager().getPresumedLoc(Field->getLocation()); - DocComment Comment; - if (auto *RawComment = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field)) - Comment = RawComment->getFormattedLines(Context.getSourceManager(), - Context.getDiagnostics()); - - // Build declaration fragments and sub-heading for the struct field. - DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForField(Field); - DeclarationFragments SubHeading = - DeclarationFragmentsBuilder::getSubHeading(Field); - - API.addRecordField( - RecordRecord, Name, USR, Loc, AvailabilityInfo::createFromDecl(Field), - Comment, Declaration, SubHeading, FieldKind, isInSystemHeader(Field)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Constant), Loc, + AvailabilityInfo::createFromDecl(Constant), Comment, Declaration, + SubHeading, isInSystemHeader(Constant)); } } template bool ExtractAPIVisitorBase::VisitFieldDecl(const FieldDecl *Decl) { - if (Decl->getDeclContext()->getDeclKind() == Decl::Record) + // ObjCIvars are handled separately + if (isa(Decl) || isa(Decl)) return true; - if (isa(Decl)) + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; + // Collect symbol information. StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -1231,22 +1220,40 @@ bool ExtractAPIVisitorBase::VisitFieldDecl(const FieldDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForField(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); - API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, - SubHeading, Access, isInSystemHeader(Decl)); + if (isa(Decl->getDeclContext())) { + AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, Access, isInSystemHeader(Decl)); + } else if (auto *RD = dyn_cast(Decl->getDeclContext())) { + if (RD->isUnion()) + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); + else + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); + } + return true; } template bool ExtractAPIVisitorBase::VisitCXXConversionDecl( const CXXConversionDecl *Decl) { - StringRef Name = API.copyString(Decl->getNameAsString()); - StringRef USR = API.recordUSR(Decl); + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || + Decl->isImplicit()) + return true; + + auto Name = Decl->getNameAsString(); + SmallString<128> USR; + index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -1264,19 +1271,17 @@ bool ExtractAPIVisitorBase::VisitCXXConversionDecl( DeclarationFragmentsBuilder::getFunctionSignature(Decl); AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - SmallString<128> ParentUSR; - index::generateUSRForDecl(dyn_cast(Decl->getDeclContext()), - ParentUSR); if (Decl->isStatic()) - API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Signature, Access, - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, Signature, Access, isInSystemHeader(Decl)); else - API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, - Declaration, SubHeading, Signature, Access, - isInSystemHeader(Decl)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, Signature, Access, isInSystemHeader(Decl)); + return true; } @@ -1291,8 +1296,9 @@ void ExtractAPIVisitorBase::recordObjCMethods( if (Method->isPropertyAccessor()) continue; - StringRef Name = API.copyString(Method->getSelector().getAsString()); - StringRef USR = API.recordUSR(Method); + auto Name = Method->getSelector().getAsString(); + SmallString<128> USR; + index::generateUSRForDecl(Method, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Method->getLocation()); DocComment Comment; @@ -1309,10 +1315,16 @@ void ExtractAPIVisitorBase::recordObjCMethods( FunctionSignature Signature = DeclarationFragmentsBuilder::getFunctionSignature(Method); - API.addObjCMethod(Container, Name, USR, Loc, - AvailabilityInfo::createFromDecl(Method), Comment, - Declaration, SubHeading, Signature, - Method->isInstanceMethod(), isInSystemHeader(Method)); + if (Method->isInstanceMethod()) + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Method), Loc, + AvailabilityInfo::createFromDecl(Method), Comment, Declaration, + SubHeading, Signature, isInSystemHeader(Method)); + else + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Method), Loc, + AvailabilityInfo::createFromDecl(Method), Comment, Declaration, + SubHeading, Signature, isInSystemHeader(Method)); } } @@ -1322,7 +1334,8 @@ void ExtractAPIVisitorBase::recordObjCProperties( const ObjCContainerDecl::prop_range Properties) { for (const auto *Property : Properties) { StringRef Name = Property->getName(); - StringRef USR = API.recordUSR(Property); + SmallString<128> USR; + index::generateUSRForDecl(Property, USR); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Property->getLocation()); DocComment Comment; @@ -1337,10 +1350,8 @@ void ExtractAPIVisitorBase::recordObjCProperties( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Property); - StringRef GetterName = - API.copyString(Property->getGetterName().getAsString()); - StringRef SetterName = - API.copyString(Property->getSetterName().getAsString()); + auto GetterName = Property->getGetterName().getAsString(); + auto SetterName = Property->getSetterName().getAsString(); // Get the attributes for property. unsigned Attributes = ObjCPropertyRecord::NoAttr; @@ -1348,14 +1359,22 @@ void ExtractAPIVisitorBase::recordObjCProperties( ObjCPropertyAttribute::kind_readonly) Attributes |= ObjCPropertyRecord::ReadOnly; - API.addObjCProperty( - Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Property), - Comment, Declaration, SubHeading, - static_cast(Attributes), GetterName, - SetterName, Property->isOptional(), - !(Property->getPropertyAttributes() & - ObjCPropertyAttribute::kind_class), - isInSystemHeader(Property)); + if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Property), Loc, + AvailabilityInfo::createFromDecl(Property), Comment, Declaration, + SubHeading, + static_cast(Attributes), + GetterName, SetterName, Property->isOptional(), + isInSystemHeader(Property)); + else + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Property), Loc, + AvailabilityInfo::createFromDecl(Property), Comment, Declaration, + SubHeading, + static_cast(Attributes), + GetterName, SetterName, Property->isOptional(), + isInSystemHeader(Property)); } } @@ -1367,7 +1386,9 @@ void ExtractAPIVisitorBase::recordObjCInstanceVariables( Ivars) { for (const auto *Ivar : Ivars) { StringRef Name = Ivar->getName(); - StringRef USR = API.recordUSR(Ivar); + SmallString<128> USR; + index::generateUSRForDecl(Ivar, USR); + PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Ivar->getLocation()); DocComment Comment; @@ -1382,12 +1403,10 @@ void ExtractAPIVisitorBase::recordObjCInstanceVariables( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Ivar); - ObjCInstanceVariableRecord::AccessControl Access = - Ivar->getCanonicalAccessControl(); - - API.addObjCInstanceVariable( - Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Ivar), - Comment, Declaration, SubHeading, Access, isInSystemHeader(Ivar)); + API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Ivar), Loc, + AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration, + SubHeading, isInSystemHeader(Ivar)); } } @@ -1396,8 +1415,7 @@ void ExtractAPIVisitorBase::recordObjCProtocols( ObjCContainerRecord *Container, ObjCInterfaceDecl::protocol_range Protocols) { for (const auto *Protocol : Protocols) - Container->Protocols.emplace_back(Protocol->getName(), - API.recordUSR(Protocol)); + Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol)); } } // namespace impl diff --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h index c67864aac9af9c..08045a30823db8 100644 --- a/clang/include/clang/ExtractAPI/FrontendActions.h +++ b/clang/include/clang/ExtractAPI/FrontendActions.h @@ -49,9 +49,6 @@ class ExtractAPIAction : public ASTFrontendAction, void EndSourceFileAction() override; static StringRef getInputBufferName() { return ""; } - - static std::unique_ptr - CreateOutputFile(CompilerInstance &CI, StringRef InFile); }; /// Wrap ExtractAPIAction on top of a pre-existing action @@ -85,9 +82,6 @@ class WrappingExtractAPIAction : public WrapperFrontendAction, /// actions. This is the place where all the gathered symbol graph /// information is emited. void EndSourceFileAction() override; - - static std::unique_ptr - CreateOutputFile(CompilerInstance &CI, StringRef InFile); }; } // namespace clang diff --git a/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h new file mode 100644 index 00000000000000..07f14f349f3dd7 --- /dev/null +++ b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h @@ -0,0 +1,172 @@ +//===- ExtractAPI/Serialization/APISetVisitor.h ----------------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the ExtractAPI APISetVisitor interface. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H +#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H + +#include "clang/ExtractAPI/API.h" + +namespace clang { +namespace extractapi { + +// A helper macro to implement short-circuiting when recursing. It +// invokes CALL_EXPR, which must be a method call, on the derived +// object (s.t. a user of RecursiveASTVisitor can override the method +// in CALL_EXPR). +#define TRY_TO(CALL_EXPR) \ + do { \ + if (!getDerived()->CALL_EXPR) \ + return false; \ + } while (false) + +/// The base interface of visitors for API information, the interface and usage +/// is almost identical to RecurisveASTVistor. This class performs three +/// distinct tasks: +/// 1. traverse the APISet (i.e. go to every record); +/// 2. at a given record, walk up the class hierarchy starting from the record's +/// dynamic type until APIRecord is reached. +/// 3. given a (record, class) combination where 'class' is some base class of +/// the dynamic type of 'record', call a user-overridable function to actually +/// visit the record. +/// +/// These tasks are done by three groups of methods, respectively: +/// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for +/// traversing the records starting from x. This method simply forwards to +/// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls +/// walkUpFromFoo(x) and then recursively visits the child records of x. +/// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of +/// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent +/// class of Foo (unless Foo has no parent) and then calls visitFoo(x). +/// 3. visitFoo(Foo *x) does task #3. +/// +/// These three method groups are tiered (traverse* > walkUpFrom* > +/// visit*). A method (e.g. traverse*) may call methods from the same +/// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*). +/// It may not call methods from a higher tier. +/// +/// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar +/// is Foo's super class) before calling visitFoo(), the result is +/// that the visit*() methods for a given record are called in the +/// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the +/// order will be visitRecord(), visitObjCPropertyRecord(), and then +/// visitObjCInstancePropertyRecord()). +/// +/// This scheme guarantees that all visit*() calls for the same record +/// are grouped together. In other words, visit*() methods for different +/// records are never interleaved. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously recurring +/// template pattern) and override any of the traverse*, walkUpFrom*, +/// and visit* methods for records where the visitor should customize +/// behavior. Most users only need to override visit*. Advanced +/// users may override traverse* and walkUpFrom* to implement custom +/// traversal strategies. Returning false from one of these overridden +/// functions will abort the entire traversal. +template class APISetVisitor { +public: + bool traverseAPISet() { + for (const APIRecord *TLR : API.getTopLevelRecords()) { + TRY_TO(traverseAPIRecord(TLR)); + } + return true; + } + + bool traverseAPIRecord(const APIRecord *Record); + bool walkUpFromAPIRecord(const APIRecord *Record) { + TRY_TO(visitAPIRecord(Record)); + return true; + } + bool visitAPIRecord(const APIRecord *Record) { return true; } + +#define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \ + bool traverse##CLASS(const CLASS *Record) { \ + TRY_TO(walkUpFrom##CLASS(Record)); \ + TRY_TO(traverseRecordContext(dyn_cast(Record))); \ + return true; \ + } + +#define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \ + bool walkUpFrom##CLASS(const CLASS *Record) { \ + TRY_TO(walkUpFrom##BASE(Record)); \ + TRY_TO(visit##CLASS(Record)); \ + return true; \ + } \ + bool visit##CLASS(const CLASS *Record) { return true; } + +#define CONCRETE_RECORD(CLASS, BASE, KIND) \ + GENERATE_TRAVERSE_METHOD(CLASS, BASE) \ + GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) + +#define ABSTRACT_RECORD(CLASS, BASE) \ + GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) + +#include "../APIRecords.inc" + +#undef GENERATE_WALKUP_AND_VISIT_METHODS +#undef GENERATE_TRAVERSE_METHOD + + bool traverseRecordContext(const RecordContext *); + +protected: + const APISet &API; + +public: + APISetVisitor() = delete; + APISetVisitor(const APISetVisitor &) = delete; + APISetVisitor(APISetVisitor &&) = delete; + APISetVisitor &operator=(const APISetVisitor &) = delete; + APISetVisitor &operator=(APISetVisitor &&) = delete; + +protected: + APISetVisitor(const APISet &API) : API(API) {} + ~APISetVisitor() = default; + + Derived *getDerived() { return static_cast(this); }; +}; + +template +bool APISetVisitor::traverseRecordContext( + const RecordContext *Context) { + if (!Context) + return true; + + for (auto *Child : Context->records()) + TRY_TO(traverseAPIRecord(Child)); + + return true; +} + +template +bool APISetVisitor::traverseAPIRecord(const APIRecord *Record) { + switch (Record->getKind()) { +#define CONCRETE_RECORD(CLASS, BASE, KIND) \ + case APIRecord::KIND: { \ + TRY_TO(traverse##CLASS(static_cast(Record))); \ + break; \ + } +#include "../APIRecords.inc" + case APIRecord::RK_Unknown: { + TRY_TO(walkUpFromAPIRecord(static_cast(Record))); + break; + } + default: + llvm_unreachable("API Record with uninstantiable kind"); + } + return true; +} + +} // namespace extractapi +} // namespace clang + +#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h deleted file mode 100644 index f0629a9ad56b03..00000000000000 --- a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h +++ /dev/null @@ -1,314 +0,0 @@ -//===- ExtractAPI/Serialization/SerializerBase.h ----------------*- 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 -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines the ExtractAPI APISetVisitor interface. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H -#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H - -#include "clang/ExtractAPI/API.h" - -namespace clang { -namespace extractapi { - -/// The base interface of visitors for API information. -template class APISetVisitor { -public: - void traverseAPISet() { - getDerived()->traverseNamespaces(); - - getDerived()->traverseGlobalVariableRecords(); - - getDerived()->traverseGlobalFunctionRecords(); - - getDerived()->traverseEnumRecords(); - - getDerived()->traverseStaticFieldRecords(); - - getDerived()->traverseCXXClassRecords(); - - getDerived()->traverseClassTemplateRecords(); - - getDerived()->traverseClassTemplateSpecializationRecords(); - - getDerived()->traverseClassTemplatePartialSpecializationRecords(); - - getDerived()->traverseCXXInstanceMethods(); - - getDerived()->traverseCXXStaticMethods(); - - getDerived()->traverseCXXMethodTemplates(); - - getDerived()->traverseCXXMethodTemplateSpecializations(); - - getDerived()->traverseCXXFields(); - - getDerived()->traverseCXXFieldTemplates(); - - getDerived()->traverseConcepts(); - - getDerived()->traverseGlobalVariableTemplateRecords(); - - getDerived()->traverseGlobalVariableTemplateSpecializationRecords(); - - getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords(); - - getDerived()->traverseGlobalFunctionTemplateRecords(); - - getDerived()->traverseGlobalFunctionTemplateSpecializationRecords(); - - getDerived()->traverseRecordRecords(); - - getDerived()->traverseObjCInterfaces(); - - getDerived()->traverseObjCProtocols(); - - getDerived()->traverseObjCCategories(); - - getDerived()->traverseMacroDefinitionRecords(); - - getDerived()->traverseTypedefRecords(); - } - - void traverseNamespaces() { - for (const auto &Namespace : API.getNamespaces()) - getDerived()->visitNamespaceRecord(*Namespace.second); - } - - void traverseGlobalFunctionRecords() { - for (const auto &GlobalFunction : API.getGlobalFunctions()) - getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second); - } - - void traverseGlobalVariableRecords() { - for (const auto &GlobalVariable : API.getGlobalVariables()) - getDerived()->visitGlobalVariableRecord(*GlobalVariable.second); - } - - void traverseEnumRecords() { - for (const auto &Enum : API.getEnums()) - getDerived()->visitEnumRecord(*Enum.second); - } - - void traverseRecordRecords() { - for (const auto &Record : API.getRecords()) - getDerived()->visitRecordRecord(*Record.second); - } - - void traverseStaticFieldRecords() { - for (const auto &StaticField : API.getStaticFields()) - getDerived()->visitStaticFieldRecord(*StaticField.second); - } - - void traverseCXXClassRecords() { - for (const auto &Class : API.getCXXClasses()) - getDerived()->visitCXXClassRecord(*Class.second); - } - - void traverseCXXMethodTemplates() { - for (const auto &MethodTemplate : API.getCXXMethodTemplates()) - getDerived()->visitMethodTemplateRecord(*MethodTemplate.second); - } - - void traverseCXXMethodTemplateSpecializations() { - for (const auto &MethodTemplateSpecialization : - API.getCXXMethodTemplateSpecializations()) - getDerived()->visitMethodTemplateSpecializationRecord( - *MethodTemplateSpecialization.second); - } - - void traverseClassTemplateRecords() { - for (const auto &ClassTemplate : API.getClassTemplates()) - getDerived()->visitClassTemplateRecord(*ClassTemplate.second); - } - - void traverseClassTemplateSpecializationRecords() { - for (const auto &ClassTemplateSpecialization : - API.getClassTemplateSpecializations()) - getDerived()->visitClassTemplateSpecializationRecord( - *ClassTemplateSpecialization.second); - } - - void traverseClassTemplatePartialSpecializationRecords() { - for (const auto &ClassTemplatePartialSpecialization : - API.getClassTemplatePartialSpecializations()) - getDerived()->visitClassTemplatePartialSpecializationRecord( - *ClassTemplatePartialSpecialization.second); - } - - void traverseCXXInstanceMethods() { - for (const auto &InstanceMethod : API.getCXXInstanceMethods()) - getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second); - } - - void traverseCXXStaticMethods() { - for (const auto &InstanceMethod : API.getCXXStaticMethods()) - getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second); - } - - void traverseCXXFields() { - for (const auto &CXXField : API.getCXXFields()) - getDerived()->visitCXXFieldRecord(*CXXField.second); - } - - void traverseCXXFieldTemplates() { - for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates()) - getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second); - } - - void traverseGlobalVariableTemplateRecords() { - for (const auto &GlobalVariableTemplate : API.getGlobalVariableTemplates()) - getDerived()->visitGlobalVariableTemplateRecord( - *GlobalVariableTemplate.second); - } - - void traverseGlobalVariableTemplateSpecializationRecords() { - for (const auto &GlobalVariableTemplateSpecialization : - API.getGlobalVariableTemplateSpecializations()) - getDerived()->visitGlobalVariableTemplateSpecializationRecord( - *GlobalVariableTemplateSpecialization.second); - } - - void traverseGlobalVariableTemplatePartialSpecializationRecords() { - for (const auto &GlobalVariableTemplatePartialSpecialization : - API.getGlobalVariableTemplatePartialSpecializations()) - getDerived()->visitGlobalVariableTemplatePartialSpecializationRecord( - *GlobalVariableTemplatePartialSpecialization.second); - } - - void traverseGlobalFunctionTemplateRecords() { - for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates()) - getDerived()->visitGlobalFunctionTemplateRecord( - *GlobalFunctionTemplate.second); - } - - void traverseGlobalFunctionTemplateSpecializationRecords() { - for (const auto &GlobalFunctionTemplateSpecialization : - API.getGlobalFunctionTemplateSpecializations()) - getDerived()->visitGlobalFunctionTemplateSpecializationRecord( - *GlobalFunctionTemplateSpecialization.second); - } - - void traverseConcepts() { - for (const auto &Concept : API.getConcepts()) - getDerived()->visitConceptRecord(*Concept.second); - } - - void traverseObjCInterfaces() { - for (const auto &Interface : API.getObjCInterfaces()) - getDerived()->visitObjCContainerRecord(*Interface.second); - } - - void traverseObjCProtocols() { - for (const auto &Protocol : API.getObjCProtocols()) - getDerived()->visitObjCContainerRecord(*Protocol.second); - } - - void traverseObjCCategories() { - for (const auto &Category : API.getObjCCategories()) - getDerived()->visitObjCCategoryRecord(*Category.second); - } - - void traverseMacroDefinitionRecords() { - for (const auto &Macro : API.getMacros()) - getDerived()->visitMacroDefinitionRecord(*Macro.second); - } - - void traverseTypedefRecords() { - for (const auto &Typedef : API.getTypedefs()) - getDerived()->visitTypedefRecord(*Typedef.second); - } - - void visitNamespaceRecord(const NamespaceRecord &Record){}; - - /// Visit a global function record. - void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){}; - - /// Visit a global variable record. - void visitGlobalVariableRecord(const GlobalVariableRecord &Record){}; - - /// Visit an enum record. - void visitEnumRecord(const EnumRecord &Record){}; - - /// Visit a record record. - void visitRecordRecord(const RecordRecord &Record){}; - - void visitStaticFieldRecord(const StaticFieldRecord &Record){}; - - void visitCXXClassRecord(const CXXClassRecord &Record){}; - - void visitClassTemplateRecord(const ClassTemplateRecord &Record){}; - - void visitClassTemplateSpecializationRecord( - const ClassTemplateSpecializationRecord &Record){}; - - void visitClassTemplatePartialSpecializationRecord( - const ClassTemplatePartialSpecializationRecord &Record){}; - - void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){}; - - void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){}; - - void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){}; - - void visitMethodTemplateSpecializationRecord( - const CXXMethodTemplateSpecializationRecord &Record){}; - - void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record){}; - - void visitGlobalVariableTemplateRecord( - const GlobalVariableTemplateRecord &Record) {} - - void visitGlobalVariableTemplateSpecializationRecord( - const GlobalVariableTemplateSpecializationRecord &Record){}; - - void visitGlobalVariableTemplatePartialSpecializationRecord( - const GlobalVariableTemplatePartialSpecializationRecord &Record){}; - - void visitGlobalFunctionTemplateRecord( - const GlobalFunctionTemplateRecord &Record){}; - - void visitGlobalFunctionTemplateSpecializationRecord( - const GlobalFunctionTemplateSpecializationRecord &Record){}; - - /// Visit an Objective-C container record. - void visitObjCContainerRecord(const ObjCContainerRecord &Record){}; - - /// Visit an Objective-C category record. - void visitObjCCategoryRecord(const ObjCCategoryRecord &Record){}; - - /// Visit a macro definition record. - void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){}; - - /// Visit a typedef record. - void visitTypedefRecord(const TypedefRecord &Record){}; - -protected: - const APISet &API; - -public: - APISetVisitor() = delete; - APISetVisitor(const APISetVisitor &) = delete; - APISetVisitor(APISetVisitor &&) = delete; - APISetVisitor &operator=(const APISetVisitor &) = delete; - APISetVisitor &operator=(APISetVisitor &&) = delete; - -protected: - APISetVisitor(const APISet &API) : API(API) {} - ~APISetVisitor() = default; - - Derived *getDerived() { return static_cast(this); }; -}; - -} // namespace extractapi -} // namespace clang - -#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h index 4249ac405fd262..724b087f7aea98 100644 --- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -17,11 +17,17 @@ #ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H +#include "clang/Basic/Module.h" #include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/APIIgnoresList.h" -#include "clang/ExtractAPI/Serialization/SerializerBase.h" +#include "clang/ExtractAPI/Serialization/APISetVisitor.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" @@ -35,7 +41,30 @@ using namespace llvm::json; /// Common options to customize the visitor output. struct SymbolGraphSerializerOption { /// Do not include unnecessary whitespaces to save space. - bool Compact; + bool Compact = true; + bool EmitSymbolLabelsForTesting = false; +}; + +/// A representation of the contents of a given module symbol graph +struct ExtendedModule { + ExtendedModule() = default; + ExtendedModule(ExtendedModule &&EM) = default; + ExtendedModule &operator=(ExtendedModule &&EM) = default; + // Copies are expensive so disable them. + ExtendedModule(const ExtendedModule &EM) = delete; + ExtendedModule &operator=(const ExtendedModule &EM) = delete; + + /// Add a symbol to the module, do not store the resulting pointer or use it + /// across insertions. + Object *addSymbol(Object &&Symbol); + + void addRelationship(Object &&Relationship); + + /// A JSON array of formatted symbols from an \c APISet. + Array Symbols; + + /// A JSON array of formatted symbol relationships from an \c APISet. + Array Relationships; }; /// The visitor that organizes API information in the Symbol Graph format. @@ -44,28 +73,54 @@ struct SymbolGraphSerializerOption { /// models an API set as a directed graph, where nodes are symbol declarations, /// and edges are relationships between the connected symbols. class SymbolGraphSerializer : public APISetVisitor { - /// A JSON array of formatted symbols in \c APISet. - Array Symbols; +private: + using Base = APISetVisitor; + /// The main symbol graph that contains symbols that are either top-level or a + /// are related to symbols defined in this product/module. + ExtendedModule MainModule; - /// A JSON array of formatted symbol relationships in \c APISet. - Array Relationships; + /// Additional symbol graphs that contain symbols that are related to symbols + /// defined in another product/module. The key of this map is the module name + /// of the extended module. + llvm::StringMap ExtendedModules; /// The Symbol Graph format version used by this serializer. static const VersionTuple FormatVersion; - /// Indicates whether child symbols should be visited. This is mainly + /// Indicates whether to take into account the extended module. This is only /// useful for \c serializeSingleSymbolSGF. - bool ShouldRecurse; + bool ForceEmitToMainModule; -public: - /// Serialize the APIs in \c APISet in the Symbol Graph format. + // Stores the references required to construct path components for the + // currently visited APIRecord. + llvm::SmallVector Hierarchy; + + /// The list of symbols to ignore. /// - /// \returns a JSON object that contains the root of the formatted - /// Symbol Graph. - Object serialize(); + /// Note: This should be consulted before emitting a symbol. + const APIIgnoresList &IgnoresList; - /// Wrap serialize(void) and write out the serialized JSON object to \p os. - void serialize(raw_ostream &os); + const bool EmitSymbolLabelsForTesting = false; + + /// The object instantiated by the last call to serializeAPIRecord. + Object *CurrentSymbol = nullptr; + + /// The module to which \p CurrentSymbol belongs too. + ExtendedModule *ModuleForCurrentSymbol = nullptr; + +public: + static void + serializeMainSymbolGraph(raw_ostream &OS, const APISet &API, + const APIIgnoresList &IgnoresList, + SymbolGraphSerializerOption Options = {}); + + static void serializeWithExtensionGraphs( + raw_ostream &MainOutput, const APISet &API, + const APIIgnoresList &IgnoresList, + llvm::function_ref< + std::unique_ptr(llvm::Twine BaseFileName)> + CreateOutputStream, + SymbolGraphSerializerOption Options = {}); /// Serialize a single symbol SGF. This is primarily used for libclang. /// @@ -75,6 +130,7 @@ class SymbolGraphSerializer : public APISetVisitor { static std::optional serializeSingleSymbolSGF(StringRef USR, const APISet &API); +private: /// The kind of a relationship between two symbols. enum RelationshipKind { /// The source symbol is a member of the target symbol. @@ -94,16 +150,32 @@ class SymbolGraphSerializer : public APISetVisitor { ExtensionTo, }; + /// Serialize a single record. + void serializeSingleRecord(const APIRecord *Record); + /// Get the string representation of the relationship kind. static StringRef getRelationshipString(RelationshipKind Kind); + void serializeRelationship(RelationshipKind Kind, + const SymbolReference &Source, + const SymbolReference &Target, + ExtendedModule &Into); + enum ConstraintKind { Conformance, ConditionalConformance }; static StringRef getConstraintString(ConstraintKind Kind); -private: - /// Just serialize the currently recorded objects in Symbol Graph format. - Object serializeCurrentGraph(); + /// Serialize the APIs in \c ExtendedModule. + /// + /// \returns a JSON object that contains the root of the formatted + /// Symbol Graph. + Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM); + + /// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and + /// write them to the provide stream. + void serializeGraphToStream(raw_ostream &OS, + SymbolGraphSerializerOption Options, + StringRef ModuleName, ExtendedModule &&EM); /// Synthesize the metadata section of the Symbol Graph format. /// @@ -117,124 +189,92 @@ class SymbolGraphSerializer : public APISetVisitor { /// by the given API set. /// Note that "module" here is not to be confused with the Clang/C++ module /// concept. - Object serializeModule() const; + Object serializeModuleObject(StringRef ModuleName) const; + + Array serializePathComponents(const APIRecord *Record) const; /// Determine if the given \p Record should be skipped during serialization. - bool shouldSkip(const APIRecord &Record) const; + bool shouldSkip(const APIRecord *Record) const; + + ExtendedModule &getModuleForCurrentSymbol(); /// Format the common API information for \p Record. /// /// This handles the shared information of all kinds of API records, - /// for example identifier and source location. The resulting object is then - /// augmented with kind-specific symbol information by the caller. - /// This method also checks if the given \p Record should be skipped during - /// serialization. + /// for example identifier, source location and path components. The resulting + /// object is then augmented with kind-specific symbol information in + /// subsequent visit* methods by accessing the \p State member variable. This + /// method also checks if the given \p Record should be skipped during + /// serialization. This should be called only once per concrete APIRecord + /// instance and the first visit* method to be called is responsible for + /// calling this. This is normally visitAPIRecord unless a walkUpFromFoo + /// method is implemented along the inheritance hierarchy in which case the + /// visitFoo method needs to call this. /// - /// \returns \c std::nullopt if this \p Record should be skipped, or a JSON - /// object containing common symbol information of \p Record. - template - std::optional serializeAPIRecord(const RecordTy &Record) const; - - /// Helper method to serialize second-level member records of \p Record and - /// the member-of relationships. - template - void serializeMembers(const APIRecord &Record, - const SmallVector> &Members); - - /// Serialize the \p Kind relationship between \p Source and \p Target. - /// - /// Record the relationship between the two symbols in - /// SymbolGraphSerializer::Relationships. - void serializeRelationship(RelationshipKind Kind, SymbolReference Source, - SymbolReference Target); - -protected: - /// The list of symbols to ignore. - /// - /// Note: This should be consulted before emitting a symbol. - const APIIgnoresList &IgnoresList; - - SymbolGraphSerializerOption Options; - - llvm::StringSet<> visitedCategories; + /// \returns \c nullptr if this \p Record should be skipped, or a pointer to + /// JSON object containing common symbol information of \p Record. Do not + /// store the returned pointer only use it to augment the object with record + /// specific information as it directly points to the object in the + /// \p ExtendedModule, the pointer won't be valid as soon as another object is + /// inserted into the module. + void serializeAPIRecord(const APIRecord *Record); public: - void visitNamespaceRecord(const NamespaceRecord &Record); - - /// Visit a global function record. - void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record); - - /// Visit a global variable record. - void visitGlobalVariableRecord(const GlobalVariableRecord &Record); - - /// Visit an enum record. - void visitEnumRecord(const EnumRecord &Record); - - /// Visit a record record. - void visitRecordRecord(const RecordRecord &Record); - - void visitStaticFieldRecord(const StaticFieldRecord &Record); + // Handle if records should be skipped at this level of the traversal to + // ensure that children of skipped records aren't serialized. + bool traverseAPIRecord(const APIRecord *Record); - void visitCXXClassRecord(const CXXClassRecord &Record); + bool visitAPIRecord(const APIRecord *Record); - void visitClassTemplateRecord(const ClassTemplateRecord &Record); - - void visitClassTemplateSpecializationRecord( - const ClassTemplateSpecializationRecord &Record); - - void visitClassTemplatePartialSpecializationRecord( - const ClassTemplatePartialSpecializationRecord &Record); - - void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record); + /// Visit a global function record. + bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record); - void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record); + bool visitCXXClassRecord(const CXXClassRecord *Record); - void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record); + bool visitClassTemplateRecord(const ClassTemplateRecord *Record); - void visitMethodTemplateSpecializationRecord( - const CXXMethodTemplateSpecializationRecord &Record); + bool visitClassTemplatePartialSpecializationRecord( + const ClassTemplatePartialSpecializationRecord *Record); - void visitCXXFieldRecord(const CXXFieldRecord &Record); + bool visitCXXMethodRecord(const CXXMethodRecord *Record); - void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record); + bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record); - void visitConceptRecord(const ConceptRecord &Record); + bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record); - void - visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record); + bool visitConceptRecord(const ConceptRecord *Record); - void visitGlobalVariableTemplateSpecializationRecord( - const GlobalVariableTemplateSpecializationRecord &Record); + bool + visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record); - void visitGlobalVariableTemplatePartialSpecializationRecord( - const GlobalVariableTemplatePartialSpecializationRecord &Record); + bool visitGlobalVariableTemplatePartialSpecializationRecord( + const GlobalVariableTemplatePartialSpecializationRecord *Record); - void - visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record); + bool + visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record); - void visitGlobalFunctionTemplateSpecializationRecord( - const GlobalFunctionTemplateSpecializationRecord &Record); + bool visitObjCContainerRecord(const ObjCContainerRecord *Record); - /// Visit an Objective-C container record. - void visitObjCContainerRecord(const ObjCContainerRecord &Record); + bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record); - /// Visit an Objective-C category record. - void visitObjCCategoryRecord(const ObjCCategoryRecord &Record); + bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record); + bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record); + bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record); - /// Visit a macro definition record. - void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record); + bool visitObjCMethodRecord(const ObjCMethodRecord *Record); - /// Visit a typedef record. - void visitTypedefRecord(const TypedefRecord &Record); + bool + visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record); - /// Serialize a single record. - void serializeSingleRecord(const APIRecord *Record); + bool walkUpFromTypedefRecord(const TypedefRecord *Record); + bool visitTypedefRecord(const TypedefRecord *Record); SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, - SymbolGraphSerializerOption Options = {}, - bool ShouldRecurse = true) - : APISetVisitor(API), ShouldRecurse(ShouldRecurse), - IgnoresList(IgnoresList), Options(Options) {} + bool EmitSymbolLabelsForTesting = false, + bool ForceEmitToMainModule = false) + : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), + IgnoresList(IgnoresList), + EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {} }; } // namespace extractapi diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 0720c8283cd75c..48f5fb44157570 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2223,6 +2223,20 @@ struct FormatStyle { /// \version 5 BreakConstructorInitializersStyle BreakConstructorInitializers; + /// If ``true``, clang-format will always break before function definition + /// parameters. + /// \code + /// true: + /// void functionDefinition( + /// int A, int B) {} + /// + /// false: + /// void functionDefinition(int A, int B) {} + /// + /// \endcode + /// \version 19 + bool BreakFunctionDefinitionParameters; + /// Break after each annotation on a field in Java files. /// \code{.java} /// true: false: @@ -4938,6 +4952,8 @@ struct FormatStyle { BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakConstructorInitializers == R.BreakConstructorInitializers && + BreakFunctionDefinitionParameters == + R.BreakFunctionDefinitionParameters && BreakInheritanceList == R.BreakInheritanceList && BreakStringLiterals == R.BreakStringLiterals && BreakTemplateDeclarations == R.BreakTemplateDeclarations && diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 8085dbcbf671a6..864af66b337069 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -15,6 +15,7 @@ #include "clang/Sema/CodeCompleteOptions.h" #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include #include @@ -387,6 +388,22 @@ class FrontendOptions { LLVM_PREFERRED_TYPE(bool) unsigned ModulesShareFileManager : 1; + /// Whether to emit symbol graph files as a side effect of compilation. + LLVM_PREFERRED_TYPE(bool) + unsigned EmitSymbolGraph : 1; + + /// Whether to emit additional symbol graphs for extended modules. + LLVM_PREFERRED_TYPE(bool) + unsigned EmitExtensionSymbolGraphs : 1; + + /// Whether to emit symbol labels for testing in generated symbol graphs + LLVM_PREFERRED_TYPE(bool) + unsigned EmitSymbolGraphSymbolLabelsForTesting : 1; + + /// Whether to emit symbol labels for testing in generated symbol graphs + LLVM_PREFERRED_TYPE(bool) + unsigned EmitPrettySymbolGraphs : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. @@ -496,10 +513,8 @@ class FrontendOptions { // ignore when extracting documentation. std::vector ExtractAPIIgnoresFileList; - // Currently this is only used as part of the `-emit-symbol-graph` - // action. // Location of output directory where symbol graph information would - // be dumped + // be dumped. This overrides regular -o output file specification std::string SymbolGraphOutputDir; /// Args to pass to the plugins diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index bba8ef4ff01739..580bf2a5d79df5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3014,6 +3014,7 @@ class Parser : public CodeCompletionHandler { void DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); SourceLocation SkipExtendedMicrosoftTypeAttributes(); void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); + void ParseNullabilityClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLKernelAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(ParsedAttributes &Attrs); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index e4717dd5baf1e8..76311b00d2fc58 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -198,6 +198,9 @@ class Sema; /// HLSL vector truncation. ICK_HLSL_Vector_Truncation, + /// HLSL non-decaying array rvalue cast. + ICK_HLSL_Array_RValue, + /// The number of conversion kinds ICK_Num_Conversion_Kinds, }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 3a1abd4c7892b8..8c98d8c7fef7a7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -33,7 +33,6 @@ #include "clang/AST/NSAPI.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" @@ -42,7 +41,6 @@ #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Module.h" -#include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PragmaKinds.h" @@ -183,6 +181,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaOpenACC; class StandardConversionSequence; class Stmt; class StringLiteral; @@ -466,9 +465,8 @@ class Sema final { // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) // 38. CUDA (SemaCUDA.cpp) // 39. HLSL Constructs (SemaHLSL.cpp) - // 40. OpenACC Constructs (SemaOpenACC.cpp) - // 41. OpenMP Directives and Clauses (SemaOpenMP.cpp) - // 42. SYCL Constructs (SemaSYCL.cpp) + // 40. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 41. SYCL Constructs (SemaSYCL.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1162,6 +1160,11 @@ class Sema final { /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaOpenACC &OpenACC() { + assert(OpenACCPtr); + return *OpenACCPtr; + } + protected: friend class Parser; friend class InitializationSequence; @@ -1192,6 +1195,8 @@ class Sema final { mutable IdentifierInfo *Ident_super; + std::unique_ptr OpenACCPtr; + ///@} // @@ -1655,6 +1660,9 @@ class Sema final { /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); + /// Add _Nullable attributes for std:: types. + void inferNullableClassAttribute(CXXRecordDecl *CRD); + enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural @@ -13351,56 +13359,6 @@ class Sema final { // // - /// \name OpenACC Constructs - /// Implementations are in SemaOpenACC.cpp - ///@{ - -public: - /// Called after parsing an OpenACC Clause so that it can be checked. - bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, - SourceLocation StartLoc); - - /// Called after the construct has been parsed, but clauses haven't been - /// parsed. This allows us to diagnose not-implemented, as well as set up any - /// state required for parsing the clauses. - void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'statement' context. - bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'Decl' context. - bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - /// Called when we encounter an associated statement for our construct, this - /// should check legality of the statement as it appertains to this Construct. - StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, - StmtResult AssocStmt); - - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc, - SourceLocation EndLoc, - StmtResult AssocStmt); - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - DeclGroupRef ActOnEndOpenACCDeclDirective(); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name OpenMP Directives and Clauses /// Implementations are in SemaOpenMP.cpp ///@{ diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h new file mode 100644 index 00000000000000..7f50d7889ad79b --- /dev/null +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -0,0 +1,74 @@ +//===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis for OpenACC constructs and +/// clauses. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H +#define LLVM_CLANG_SEMA_SEMAOPENACC_H + +#include "clang/AST/DeclGroup.h" +#include "clang/Basic/OpenACCKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/Ownership.h" + +namespace clang { + +class ASTContext; +class DiagnosticEngine; +class LangOptions; +class Sema; + +class SemaOpenACC { +public: + SemaOpenACC(Sema &S); + + ASTContext &getASTContext() const; + DiagnosticsEngine &getDiagnostics() const; + const LangOptions &getLangOpts() const; + + Sema &SemaRef; + + /// Called after parsing an OpenACC Clause so that it can be checked. + bool ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc); + + /// Called after the construct has been parsed, but clauses haven't been + /// parsed. This allows us to diagnose not-implemented, as well as set up any + /// state required for parsing the clauses. + void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'statement' context. + bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'Decl' context. + bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); + /// Called when we encounter an associated statement for our construct, this + /// should check legality of the statement as it appertains to this Construct. + StmtResult ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt); + + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc, + SourceLocation EndLoc, StmtResult AssocStmt); + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + DeclGroupRef ActOnEndDeclDirective(); +}; + +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMAOPENACC_H diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index f31efa5117f0d1..f762116fea956c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -41,7 +41,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 29; +const unsigned VERSION_MAJOR = 30; /// AST file minor version number supported by this version of /// Clang. diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 3ed9803fa3745b..214eb3601148b0 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -542,6 +542,7 @@ class ASTWriter : public ASTDeserializationListener, void WriteReferencedSelectorsPool(Sema &SemaRef); void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); + void WriteDeclAndTypes(ASTContext &Context); void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord); void WriteDeclContextVisibleUpdate(const DeclContext *DC); void WriteFPPragmaOptions(const FPOptionsOverride &Opts); @@ -846,7 +847,7 @@ class ASTWriter : public ASTDeserializationListener, /// AST and semantic-analysis consumer that generates a /// precompiled header from the parsed source code. class PCHGenerator : public SemaConsumer { - const Preprocessor &PP; + Preprocessor &PP; std::string OutputFile; std::string isysroot; Sema *SemaPtr; @@ -867,11 +868,12 @@ class PCHGenerator : public SemaConsumer { DiagnosticsEngine &getDiagnostics() const { return SemaPtr->getDiagnostics(); } + Preprocessor &getPreprocessor() { return PP; } virtual Module *getEmittingModule(ASTContext &Ctx); public: - PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, + PCHGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, StringRef isysroot, std::shared_ptr Buffer, ArrayRef> Extensions, @@ -893,7 +895,7 @@ class ReducedBMIGenerator : public PCHGenerator { virtual Module *getEmittingModule(ASTContext &Ctx) override; public: - ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, + ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile); void HandleTranslationUnit(ASTContext &Ctx) override; diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index 3c82dfed9497d5..82b053d4caca63 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -66,5 +66,6 @@ TYPE_BIT_CODE(Using, USING, 54) TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55) TYPE_BIT_CODE(PackIndexing, PACK_INDEXING, 56) TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57) +TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58) #undef TYPE_BIT_CODE diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c90fafb6f653d0..f7f55dc4e7a9f4 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -879,7 +879,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()), DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()), - CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), + ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()), + SourceMgr(SM), LangOpts(LOpts), NoSanitizeL(new NoSanitizeList(LangOpts.NoSanitizeFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, LangOpts.XRayNeverInstrumentFiles, @@ -1906,7 +1907,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::IncompleteArray: case Type::VariableArray: - case Type::ConstantArray: { + case Type::ConstantArray: + case Type::ArrayParameter: { // Model non-constant sized arrays as size zero, but track the alignment. uint64_t Size = 0; if (const auto *CAT = dyn_cast(T)) @@ -3396,6 +3398,37 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getArrayParameterType(QualType Ty) const { + if (Ty->isArrayParameterType()) + return Ty; + assert(Ty->isConstantArrayType() && "Ty must be an array type."); + const auto *ATy = cast(Ty); + llvm::FoldingSetNodeID ID; + ATy->Profile(ID, *this, ATy->getElementType(), ATy->getZExtSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); + void *InsertPos = nullptr; + ArrayParameterType *AT = + ArrayParameterTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + + QualType Canonical; + if (!Ty.isCanonical()) { + Canonical = getArrayParameterType(getCanonicalType(Ty)); + + // Get the new insert position for the node we care about. + AT = ArrayParameterTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); + } + + AT = new (*this, alignof(ArrayParameterType)) + ArrayParameterType(ATy, Canonical); + Types.push_back(AT); + ArrayParameterTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); +} + /// getBlockPointerType - Return the uniqued reference to the type for /// a pointer to the specified block. QualType ASTContext::getBlockPointerType(QualType T) const { @@ -3642,6 +3675,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::PackIndexing: case Type::BitInt: case Type::DependentBitInt: + case Type::ArrayParameter: llvm_unreachable("type should never be variably-modified"); // These types can be variably-modified but should never need to @@ -6051,7 +6085,9 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const { T = getVariableArrayDecayedType(T); const Type *Ty = T.getTypePtr(); QualType Result; - if (isa(Ty)) { + if (getLangOpts().HLSL && isa(Ty)) { + Result = getArrayParameterType(QualType(Ty, 0)); + } else if (isa(Ty)) { Result = getArrayDecayedType(QualType(Ty,0)); } else if (isa(Ty)) { Result = getPointerType(QualType(Ty, 0)); @@ -6973,6 +7009,8 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { + if (getLangOpts().HLSL && T->isConstantArrayType()) + return getArrayParameterType(T); if (T->isArrayType() || T->isFunctionType()) return getDecayedType(T); return T; @@ -8583,6 +8621,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, case Type::DeducedTemplateSpecialization: return; + case Type::ArrayParameter: case Type::Pipe: #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) @@ -10926,6 +10965,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, assert(LHS != RHS && "Equivalent pipe types should have already been handled!"); return {}; + case Type::ArrayParameter: + assert(LHS != RHS && + "Equivalent ArrayParameter types should have already been handled!"); + return {}; case Type::BitInt: { // Merge two bit-precise int types, while trying to preserve typedef info. bool LHSUnsigned = LHS->castAs()->isUnsigned(); @@ -12817,6 +12860,18 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, getCommonArrayElementType(Ctx, AX, QX, AY, QY), AX->getSize(), SizeExpr, getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY)); } + case Type::ArrayParameter: { + const auto *AX = cast(X), + *AY = cast(Y); + assert(AX->getSize() == AY->getSize()); + const Expr *SizeExpr = Ctx.hasSameExpr(AX->getSizeExpr(), AY->getSizeExpr()) + ? AX->getSizeExpr() + : nullptr; + auto ArrayTy = Ctx.getConstantArrayType( + getCommonArrayElementType(Ctx, AX, QX, AY, QY), AX->getSize(), SizeExpr, + getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY)); + return Ctx.getArrayParameterType(ArrayTy); + } case Type::Atomic: { const auto *AX = cast(X), *AY = cast(Y); return Ctx.getAtomicType( @@ -13078,6 +13133,7 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, CANONICAL_TYPE(Builtin) CANONICAL_TYPE(Complex) CANONICAL_TYPE(ConstantArray) + CANONICAL_TYPE(ArrayParameter) CANONICAL_TYPE(ConstantMatrix) CANONICAL_TYPE(Enum) CANONICAL_TYPE(ExtVector) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 786695f00fadcc..94a47a8f619018 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1218,6 +1218,15 @@ ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { T->getIndexTypeCVRQualifiers()); } +ExpectedType +ASTNodeImporter::VisitArrayParameterType(const ArrayParameterType *T) { + ExpectedType ToArrayTypeOrErr = VisitConstantArrayType(T); + if (!ToArrayTypeOrErr) + return ToArrayTypeOrErr.takeError(); + + return Importer.getToContext().getArrayParameterType(*ToArrayTypeOrErr); +} + ExpectedType ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 226e0aa38ece70..d56bf21b459e03 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -840,6 +840,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: if (!IsStructurallyEquivalent(Context, cast(T1)->getOriginalType(), cast(T2)->getOriginalType())) diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 9d3856b8f7e08a..86b77b49a0fbc4 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -654,6 +654,9 @@ ExprDependence clang::computeDependence(MemberExpr *E) { D |= toExprDependence(NNS->getDependence() & ~NestedNameSpecifierDependence::Dependent); + for (const auto &A : E->template_arguments()) + D |= toExprDependence(A.getArgument().getDependence()); + auto *MemberDecl = E->getMemberDecl(); if (FieldDecl *FD = dyn_cast(MemberDecl)) { DeclContext *DC = MemberDecl->getDeclContext(); @@ -670,7 +673,6 @@ ExprDependence clang::computeDependence(MemberExpr *E) { D |= ExprDependence::Type; } } - // FIXME: move remaining dependence computation from MemberExpr::Create() return D; } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 2cbb86b31b5e2e..66a727d9dd0c39 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1852,9 +1852,9 @@ DeclContext::lookup(DeclarationName Name) const { DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(getDeclKind() != Decl::LinkageSpec && - getDeclKind() != Decl::Export && - "should not perform lookups into transparent contexts"); + // For transparent DeclContext, we should lookup in their enclosing context. + if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export) + return getParent()->noload_lookup(Name); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 6221ebd5c9b4e9..07c9f287dd0767 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1712,8 +1712,11 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( } MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, - ValueDecl *MemberDecl, - const DeclarationNameInfo &NameInfo, QualType T, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl), @@ -1721,11 +1724,30 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, assert(!NameInfo.getName() || MemberDecl->getDeclName() == NameInfo.getName()); MemberExprBits.IsArrow = IsArrow; - MemberExprBits.HasQualifierOrFoundDecl = false; - MemberExprBits.HasTemplateKWAndArgsInfo = false; + MemberExprBits.HasQualifier = QualifierLoc.hasQualifier(); + MemberExprBits.HasFoundDecl = + FoundDecl.getDecl() != MemberDecl || + FoundDecl.getAccess() != MemberDecl->getAccess(); + MemberExprBits.HasTemplateKWAndArgsInfo = + TemplateArgs || TemplateKWLoc.isValid(); MemberExprBits.HadMultipleCandidates = false; MemberExprBits.NonOdrUseReason = NOUR; MemberExprBits.OperatorLoc = OperatorLoc; + + if (hasQualifier()) + new (getTrailingObjects()) + NestedNameSpecifierLoc(QualifierLoc); + if (hasFoundDecl()) + *getTrailingObjects() = FoundDecl; + if (TemplateArgs) { + auto Deps = TemplateArgumentDependence::None; + getTrailingObjects()->initializeFrom( + TemplateKWLoc, *TemplateArgs, getTrailingObjects(), + Deps); + } else if (TemplateKWLoc.isValid()) { + getTrailingObjects()->initializeFrom( + TemplateKWLoc); + } setDependence(computeDependence(this)); } @@ -1735,48 +1757,20 @@ MemberExpr *MemberExpr::Create( ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) { - bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl || - FoundDecl.getAccess() != MemberDecl->getAccess(); + bool HasQualifier = QualifierLoc.hasQualifier(); + bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl || + FoundDecl.getAccess() != MemberDecl->getAccess(); bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); std::size_t Size = - totalSizeToAlloc( - HasQualOrFound ? 1 : 0, HasTemplateKWAndArgsInfo ? 1 : 0, + totalSizeToAlloc( + HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); void *Mem = C.Allocate(Size, alignof(MemberExpr)); - MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, - NameInfo, T, VK, OK, NOUR); - - if (HasQualOrFound) { - E->MemberExprBits.HasQualifierOrFoundDecl = true; - - MemberExprNameQualifier *NQ = - E->getTrailingObjects(); - NQ->QualifierLoc = QualifierLoc; - NQ->FoundDecl = FoundDecl; - } - - E->MemberExprBits.HasTemplateKWAndArgsInfo = - TemplateArgs || TemplateKWLoc.isValid(); - - // FIXME: remove remaining dependence computation to computeDependence(). - auto Deps = E->getDependence(); - if (TemplateArgs) { - auto TemplateArgDeps = TemplateArgumentDependence::None; - E->getTrailingObjects()->initializeFrom( - TemplateKWLoc, *TemplateArgs, - E->getTrailingObjects(), TemplateArgDeps); - for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments()) { - Deps |= toExprDependence(ArgLoc.getArgument().getDependence()); - } - } else if (TemplateKWLoc.isValid()) { - E->getTrailingObjects()->initializeFrom( - TemplateKWLoc); - } - E->setDependence(Deps); - - return E; + return new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, QualifierLoc, + TemplateKWLoc, MemberDecl, FoundDecl, NameInfo, + TemplateArgs, T, VK, OK, NOUR); } MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, @@ -1785,12 +1779,11 @@ MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, unsigned NumTemplateArgs) { assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) && "template args but no template arg info?"); - bool HasQualOrFound = HasQualifier || HasFoundDecl; std::size_t Size = - totalSizeToAlloc(HasQualOrFound ? 1 : 0, - HasTemplateKWAndArgsInfo ? 1 : 0, - NumTemplateArgs); + totalSizeToAlloc( + HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, + NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(MemberExpr)); return new (Mem) MemberExpr(EmptyShell()); } @@ -1948,6 +1941,7 @@ bool CastExpr::CastConsistency() const { case CK_UserDefinedConversion: // operator bool() case CK_BuiltinFnToFnPtr: case CK_FixedPointToBoolean: + case CK_HLSLArrayRValue: CheckNoBasePath: assert(path_empty() && "Cast kind should not have a base path!"); break; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index dae8f32fc02951..88c8eaf6ef9b6e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6456,7 +6456,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. assert(!BaseIt->isVirtual() && "virtual base for literal type"); - assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && + assert(Info.Ctx.hasSameUnqualifiedType(BaseIt->getType(), BaseType) && "base class initializers not in expected order"); ++BaseIt; #endif @@ -11699,6 +11699,7 @@ GCCTypeClass EvaluateBuiltinClassifyType(QualType T, case Type::IncompleteArray: case Type::FunctionNoProto: case Type::FunctionProto: + case Type::ArrayParameter: return GCCTypeClass::Pointer; case Type::MemberPointer: @@ -14085,6 +14086,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AtomicToNonAtomic: case CK_NoOp: case CK_LValueToRValueBitCast: + case CK_HLSLArrayRValue: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_MemberPointerToBoolean: @@ -14913,6 +14915,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AtomicToNonAtomic: case CK_NoOp: case CK_LValueToRValueBitCast: + case CK_HLSLArrayRValue: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_Dependent: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 425f84e8af1fe7..d632c697fa20db 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2398,6 +2398,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Complex: case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -4446,6 +4447,10 @@ void CXXNameMangler::mangleType(const DependentBitIntType *T) { Out << "_"; } +void CXXNameMangler::mangleType(const ArrayParameterType *T) { + mangleType(cast(T)); +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // ::= L E # integer literal diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index addc3140546a46..a0bb04e69c9be8 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -3079,6 +3079,11 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { mangleType(ElementTy, SourceRange(), QMM_Escape); } +void MicrosoftCXXNameMangler::mangleType(const ArrayParameterType *T, + Qualifiers, SourceRange) { + mangleArrayType(cast(T)); +} + // ::= // ::= // diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 2dbc259138a897..e159a1b00be552 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -944,6 +944,10 @@ class ODRTypeVisitor : public TypeVisitor { VisitArrayType(T); } + void VisitArrayParameterType(const ArrayParameterType *T) { + VisitConstantArrayType(T); + } + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { AddStmt(T->getSizeExpr()); VisitArrayType(T); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 8f3e26d4601921..cb22c91a12aa89 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1197,6 +1197,14 @@ struct SimpleTransformVisitor : public TypeVisitor { return Ctx.getDecayedType(originalType); } + QualType VisitArrayParameterType(const ArrayParameterType *T) { + QualType ArrTy = VisitConstantArrayType(T); + if (ArrTy.isNull()) + return {}; + + return Ctx.getArrayParameterType(ArrTy); + } + SUGARED_TYPE_CLASS(TypeOfExpr) SUGARED_TYPE_CLASS(TypeOf) SUGARED_TYPE_CLASS(Decltype) @@ -4454,6 +4462,7 @@ static CachedProperties computeCachedProperties(const Type *T) { case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: return Cache::get(cast(T)->getElementType()); case Type::Vector: case Type::ExtVector: @@ -4542,6 +4551,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: return computeTypeLinkageInfo(cast(T)->getElementType()); case Type::Vector: case Type::ExtVector: @@ -4642,16 +4652,15 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::Auto: return ResultIfUnknown; - // Dependent template specializations can instantiate to pointer - // types unless they're known to be specializations of a class - // template. + // Dependent template specializations could instantiate to pointer types. case Type::TemplateSpecialization: - if (TemplateDecl *templateDecl - = cast(type.getTypePtr()) - ->getTemplateName().getAsTemplateDecl()) { - if (isa(templateDecl)) - return false; - } + // If it's a known class template, we can already check if it's nullable. + if (TemplateDecl *templateDecl = + cast(type.getTypePtr()) + ->getTemplateName() + .getAsTemplateDecl()) + if (auto *CTD = dyn_cast(templateDecl)) + return CTD->getTemplatedDecl()->hasAttr(); return ResultIfUnknown; case Type::Builtin: @@ -4708,6 +4717,17 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { } llvm_unreachable("unknown builtin type"); + case Type::Record: { + const RecordDecl *RD = cast(type)->getDecl(); + // For template specializations, look only at primary template attributes. + // This is a consistent regardless of whether the instantiation is known. + if (const auto *CTSD = dyn_cast(RD)) + return CTSD->getSpecializedTemplate() + ->getTemplatedDecl() + ->hasAttr(); + return RD->hasAttr(); + } + // Non-pointer types. case Type::Complex: case Type::LValueReference: @@ -4725,7 +4745,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::DependentAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: - case Type::Record: case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: @@ -4736,6 +4755,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::Pipe: case Type::BitInt: case Type::DependentBitInt: + case Type::ArrayParameter: return false; } llvm_unreachable("bad type kind!"); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 0aa1d9327d7707..9d551ff83151fd 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -268,6 +268,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -595,6 +596,16 @@ void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) { printAdjustedBefore(T, OS); } +void TypePrinter::printArrayParameterAfter(const ArrayParameterType *T, + raw_ostream &OS) { + printConstantArrayAfter(T, OS); +} + +void TypePrinter::printArrayParameterBefore(const ArrayParameterType *T, + raw_ostream &OS) { + printConstantArrayBefore(T, OS); +} + void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) { printAdjustedAfter(T, OS); } diff --git a/clang/lib/Basic/Targets/M68k.cpp b/clang/lib/Basic/Targets/M68k.cpp index 1b7e0a7f32c9be..8b8bf97d6f99a1 100644 --- a/clang/lib/Basic/Targets/M68k.cpp +++ b/clang/lib/Basic/Targets/M68k.cpp @@ -127,16 +127,21 @@ bool M68kTargetInfo::hasFeature(StringRef Feature) const { const char *const M68kTargetInfo::GCCRegNames[] = { "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", "pc"}; ArrayRef M68kTargetInfo::getGCCRegNames() const { return llvm::ArrayRef(GCCRegNames); } +const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = { + {{"bp"}, "a5"}, + {{"fp"}, "a6"}, + {{"usp", "ssp", "isp", "a7"}, "sp"}, +}; + ArrayRef M68kTargetInfo::getGCCRegAliases() const { - // No aliases. - return std::nullopt; + return llvm::ArrayRef(GCCRegAliases); } bool M68kTargetInfo::validateAsmConstraint( diff --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h index a9c262e62fbad0..7ffa901127e504 100644 --- a/clang/lib/Basic/Targets/M68k.h +++ b/clang/lib/Basic/Targets/M68k.h @@ -25,6 +25,7 @@ namespace targets { class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo { static const char *const GCCRegNames[]; + static const TargetInfo::GCCRegAlias GCCRegAliases[]; enum CPUKind { CK_Unknown, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 82b30b8d815629..c8b2a93ae47add 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -100,21 +100,20 @@ using namespace llvm; namespace llvm { extern cl::opt PrintPipelinePasses; -cl::opt ClRemoveTraps("clang-remove-traps", cl::Optional, - cl::desc("Insert remove-traps pass."), - cl::init(false)); +static cl::opt ClRemoveTraps("clang-remove-traps", cl::Optional, + cl::desc("Insert remove-traps pass.")); // Experiment to move sanitizers earlier. static cl::opt ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, - cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false)); + cl::desc("Insert sanitizers on OptimizerEarlyEP.")); extern cl::opt ProfileCorrelate; // Re-link builtin bitcodes after optimization cl::opt ClRelinkBuiltinBitcodePostop( "relink-builtin-bitcode-postop", cl::Optional, - cl::desc("Re-link builtin bitcodes after optimization."), cl::init(false)); + cl::desc("Re-link builtin bitcodes after optimization.")); } // namespace llvm namespace { diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 56198385de9dcb..d35ce0409d7232 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -197,11 +197,11 @@ namespace { llvm::Value *getScalarRValValueOrNull(RValue RVal) const; /// Converts an rvalue to integer value if needed. - llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const; + llvm::Value *convertRValueToInt(RValue RVal, bool CmpXchg = false) const; RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot, SourceLocation Loc, bool AsValue, - bool CastFP = true) const; + bool CmpXchg = false) const; /// Copy an atomic r-value into atomic-layout memory. void emitCopyIntoMemory(RValue rvalue) const; @@ -264,7 +264,7 @@ namespace { llvm::AtomicOrdering AO, bool IsVolatile); /// Emits atomic load as LLVM instruction. llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile, - bool CastFP = true); + bool CmpXchg = false); /// Emits atomic compare-and-exchange op as a libcall. llvm::Value *EmitAtomicCompareExchangeLibcall( llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr, @@ -1401,13 +1401,26 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr, LVal.getBaseInfo(), TBAAAccessInfo())); } +/// Return true if \param ValTy is a type that should be casted to integer +/// around the atomic memory operation. If \param CmpXchg is true, then the +/// cast of a floating point type is made as that instruction can not have +/// floating point operands. TODO: Allow compare-and-exchange and FP - see +/// comment in AtomicExpandPass.cpp. +static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) { + if (ValTy->isFloatingPointTy()) + return ValTy->isX86_FP80Ty() || CmpXchg; + return !ValTy->isIntegerTy() && !ValTy->isPointerTy(); +} + RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val, AggValueSlot ResultSlot, SourceLocation Loc, bool AsValue, - bool CastFP) const { + bool CmpXchg) const { // Try not to in some easy cases. - assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) && - "Expected integer or floating point value"); + assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() || + Val->getType()->isIEEELikeFPTy()) && + "Expected integer, pointer or floating point value when converting " + "result."); if (getEvaluationKind() == TEK_Scalar && (((!LVal.isBitField() || LVal.getBitFieldInfo().Size == ValueSizeInBits) && @@ -1416,13 +1429,12 @@ RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val, auto *ValTy = AsValue ? CGF.ConvertTypeForMem(ValueTy) : getAtomicAddress().getElementType(); - if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) { + if (!shouldCastToInt(ValTy, CmpXchg)) { assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) && "Different integer types."); return RValue::get(CGF.EmitFromMemory(Val, ValueTy)); - } else if (ValTy->isPointerTy()) - return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy)); - else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy)) + } + if (llvm::CastInst::isBitCastable(Val->getType(), ValTy)) return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy)); } @@ -1459,10 +1471,10 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, } llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO, - bool IsVolatile, bool CastFP) { + bool IsVolatile, bool CmpXchg) { // Okay, we're doing this natively. Address Addr = getAtomicAddress(); - if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP)) + if (shouldCastToInt(Addr.getElementType(), CmpXchg)) Addr = castToAtomicIntPointer(Addr); llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load"); Load->setAtomic(AO); @@ -1523,7 +1535,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } // Okay, we're doing this natively. - auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false); + auto *Load = EmitAtomicLoadOp(AO, IsVolatile); // If we're ignoring an aggregate return, don't do anything. if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored()) @@ -1531,8 +1543,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, // Okay, turn that back into the original value or atomic (for non-simple // lvalues) type. - return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue, - /*CastFP=*/false); + return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue); } /// Emit a load from an l-value of atomic type. Note that the r-value @@ -1601,20 +1612,17 @@ llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const { return nullptr; } -llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const { +llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CmpXchg) const { // If we've got a scalar value of the right size, try to avoid going // through memory. Floats get casted if needed by AtomicExpandPass. if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) { - if (isa(Value->getType()) || - (!CastFP && Value->getType()->isIEEELikeFPTy())) + if (!shouldCastToInt(Value->getType(), CmpXchg)) return CGF.EmitToMemory(Value, ValueTy); else { llvm::IntegerType *InputIntTy = llvm::IntegerType::get( CGF.getLLVMContext(), LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits()); - if (isa(Value->getType())) - return CGF.Builder.CreatePtrToInt(Value, InputIntTy); - else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy)) + if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy)) return CGF.Builder.CreateBitCast(Value, InputIntTy); } } @@ -1687,13 +1695,14 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( // If we've got a scalar value of the right size, try to avoid going // through memory. - auto *ExpectedVal = convertRValueToInt(Expected); - auto *DesiredVal = convertRValueToInt(Desired); + auto *ExpectedVal = convertRValueToInt(Expected, /*CmpXchg=*/true); + auto *DesiredVal = convertRValueToInt(Desired, /*CmpXchg=*/true); auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success, Failure, IsWeak); return std::make_pair( ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false), + SourceLocation(), /*AsValue=*/false, + /*CmpXchg=*/true), Res.second); } @@ -1787,7 +1796,7 @@ void AtomicInfo::EmitAtomicUpdateOp( auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile); + auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true); // For non-simple lvalues perform compare-and-swap procedure. auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); @@ -1803,7 +1812,8 @@ void AtomicInfo::EmitAtomicUpdateOp( CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); } auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false); + SourceLocation(), /*AsValue=*/false, + /*CmpXchg=*/true); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr); auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr); // Try to write new value using cmpxchg operation. @@ -1869,7 +1879,7 @@ void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal, auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile); + auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true); // For non-simple lvalues perform compare-and-swap procedure. auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); @@ -1969,21 +1979,16 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, } // Okay, we're doing this natively. - llvm::Value *ValToStore = - atomics.convertRValueToInt(rvalue, /*CastFP=*/false); + llvm::Value *ValToStore = atomics.convertRValueToInt(rvalue); // Do the atomic store. Address Addr = atomics.getAtomicAddress(); - bool ShouldCastToInt = true; if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue)) - if (isa(Value->getType()) || - Value->getType()->isIEEELikeFPTy()) - ShouldCastToInt = false; - if (ShouldCastToInt) { - Addr = atomics.castToAtomicIntPointer(Addr); - ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(), - /*isSigned=*/false); - } + if (shouldCastToInt(Value->getType(), /*CmpXchg=*/false)) { + Addr = atomics.castToAtomicIntPointer(Addr); + ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(), + /*isSigned=*/false); + } llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr); if (AO == llvm::AtomicOrdering::Acquire) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index bb007231c0b783..483f9c26859923 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5835,7 +5835,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitLifetimeEnd(TmpSize, TmpPtr); return Call; } - [[fallthrough]]; + llvm_unreachable("Unexpected enqueue_kernel signature"); } // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a5fe39633679b9..f12765b826935b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4379,7 +4379,8 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); bool CanCheckNullability = false; - if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { + if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD && + !PVD->getType()->isRecordType()) { auto Nullability = PVD->getType()->getNullability(); CanCheckNullability = Nullability && *Nullability == NullabilityKind::NonNull && @@ -4719,7 +4720,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, } if (HasAggregateEvalKind && isa(E) && - cast(E)->getCastKind() == CK_LValueToRValue) { + cast(E)->getCastKind() == CK_LValueToRValue && + !type->isArrayParameterType()) { LValue L = EmitLValue(cast(E)->getSubExpr()); assert(L.isSimple()); args.addUncopiedAggregate(L, type); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 691fde8b0d8b82..8c284c332171a1 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3641,6 +3641,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: + case Type::ArrayParameter: return CreateType(cast(Ty), Unit); case Type::LValueReference: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 36872c0fedb76e..54432353e7420d 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -56,8 +56,7 @@ using namespace CodeGen; // Experiment to make sanitizers easier to debug static llvm::cl::opt ClSanitizeDebugDeoptimization( "ubsan-unique-traps", llvm::cl::Optional, - llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"), - llvm::cl::init(false)); + llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check")); //===--------------------------------------------------------------------===// // Miscellaneous Helper Methods @@ -5190,6 +5189,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_IntegralToFixedPoint: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 143855aa84ca3f..1b9287ea239347 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -883,6 +883,9 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { [[fallthrough]]; + case CK_HLSLArrayRValue: + Visit(E->getSubExpr()); + break; case CK_NoOp: case CK_UserDefinedConversion: @@ -1524,6 +1527,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_LValueToRValue: case CK_LValueToRValueBitCast: case CK_UncheckedDerivedToBase: + case CK_HLSLArrayRValue: return false; } llvm_unreachable("Unhandled clang::CastKind enum"); diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index c3774d0cb75edc..a793b214645cb3 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -616,6 +616,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_IntegralToFixedPoint: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 36d7493d9a6baf..9f1b06eebf9ed0 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1226,6 +1226,7 @@ class ConstExprEmitter : case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: return nullptr; } llvm_unreachable("Invalid CastKind"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 83247aa48f8609..397b4977acc3e9 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2329,6 +2329,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_FloatingComplexToIntegralComplex: case CK_ConstructorConversion: case CK_ToUnion: + case CK_HLSLArrayRValue: llvm_unreachable("scalar cast to non-scalar value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index e32023aeac1e6f..634a55fec5182e 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -185,9 +185,10 @@ struct CGRecordLowering { /// Lowers an ASTRecordLayout to a llvm type. void lower(bool NonVirtualBaseType); void lowerUnion(bool isNoUniqueAddress); - void accumulateFields(); + void accumulateFields(bool isNonVirtualBaseType); RecordDecl::field_iterator - accumulateBitFields(RecordDecl::field_iterator Field, + accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd); void computeVolatileBitfields(); void accumulateBases(); @@ -195,8 +196,10 @@ struct CGRecordLowering { void accumulateVBases(); /// Recursively searches all of the bases to find out if a vbase is /// not the primary vbase of some base class. - bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query); + bool hasOwnStorage(const CXXRecordDecl *Decl, + const CXXRecordDecl *Query) const; void calculateZeroInit(); + CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const; /// Lowers bitfield storage types to I8 arrays for bitfields with tail /// padding that is or can potentially be used. void clipTailPadding(); @@ -287,7 +290,7 @@ void CGRecordLowering::lower(bool NVBaseType) { computeVolatileBitfields(); return; } - accumulateFields(); + accumulateFields(NVBaseType); // RD implies C++. if (RD) { accumulateVPtrs(); @@ -378,12 +381,12 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { Packed = true; } -void CGRecordLowering::accumulateFields() { +void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) { for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd;) { if (Field->isBitField()) { - Field = accumulateBitFields(Field, FieldEnd); + Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd); assert((Field == FieldEnd || !Field->isBitField()) && "Failed to accumulate all the bitfields"); } else if (Field->isZeroSize(Context)) { @@ -404,9 +407,12 @@ void CGRecordLowering::accumulateFields() { } // Create members for bitfields. Field is a bitfield, and FieldEnd is the end -// iterator of the record. Return the first non-bitfield encountered. +// iterator of the record. Return the first non-bitfield encountered. We need +// to know whether this is the base or complete layout, as virtual bases could +// affect the upper bound of bitfield access unit allocation. RecordDecl::field_iterator -CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, +CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd) { if (isDiscreteBitFieldABI()) { // Run stores the first element of the current run of bitfields. FieldEnd is @@ -505,6 +511,10 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, bitsToCharUnits(Context.getTargetInfo().getRegisterWidth()); unsigned CharBits = Context.getCharWidth(); + // Limit of useable tail padding at end of the record. Computed lazily and + // cached here. + CharUnits ScissorOffset = CharUnits::Zero(); + // Data about the start of the span we're accumulating to create an access // unit from. Begin is the first bitfield of the span. If Begin is FieldEnd, // we've not got a current span. The span starts at the BeginOffset character @@ -630,10 +640,14 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe)); goto FoundLimit; } - // We reached the end of the fields. We can't necessarily use tail - // padding in C++ structs, so the NonVirtual size is what we must - // use there. - LimitOffset = RD ? Layout.getNonVirtualSize() : Layout.getDataSize(); + // We reached the end of the fields, determine the bounds of useable + // tail padding. As this can be complex for C++, we cache the result. + if (ScissorOffset.isZero()) { + ScissorOffset = calculateTailClippingOffset(isNonVirtualBaseType); + assert(!ScissorOffset.isZero() && "Tail clipping at zero"); + } + + LimitOffset = ScissorOffset; FoundLimit:; CharUnits TypeSize = getSize(Type); @@ -838,13 +852,17 @@ void CGRecordLowering::accumulateVPtrs() { llvm::PointerType::getUnqual(Types.getLLVMContext()))); } -void CGRecordLowering::accumulateVBases() { +CharUnits +CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const { + if (!RD) + return Layout.getDataSize(); + CharUnits ScissorOffset = Layout.getNonVirtualSize(); // In the itanium ABI, it's possible to place a vbase at a dsize that is // smaller than the nvsize. Here we check to see if such a base is placed // before the nvsize and set the scissor offset to that, instead of the // nvsize. - if (isOverlappingVBaseABI()) + if (!isNonVirtualBaseType && isOverlappingVBaseABI()) for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (BaseDecl->isEmpty()) @@ -856,8 +874,13 @@ void CGRecordLowering::accumulateVBases() { ScissorOffset = std::min(ScissorOffset, Layout.getVBaseClassOffset(BaseDecl)); } - Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr, - RD)); + + return ScissorOffset; +} + +void CGRecordLowering::accumulateVBases() { + Members.push_back(MemberInfo(calculateTailClippingOffset(false), + MemberInfo::Scissor, nullptr, RD)); for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (BaseDecl->isEmpty()) @@ -882,7 +905,7 @@ void CGRecordLowering::accumulateVBases() { } bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl, - const CXXRecordDecl *Query) { + const CXXRecordDecl *Query) const { const ASTRecordLayout &DeclLayout = Context.getASTRecordLayout(Decl); if (DeclLayout.isPrimaryBaseVirtual() && DeclLayout.getPrimaryBase() == Query) return false; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 44103884940fd9..6474d6c8c1d1e4 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -276,6 +276,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::Record: case Type::ObjCObject: case Type::ObjCInterface: + case Type::ArrayParameter: return TEK_Aggregate; // We operate on atomic values according to their underlying type. @@ -989,7 +990,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // return value. Initialize the flag to 'true' and refine it in EmitParmDecl. if (SanOpts.has(SanitizerKind::NullabilityReturn)) { auto Nullability = FnRetTy->getNullability(); - if (Nullability && *Nullability == NullabilityKind::NonNull) { + if (Nullability && *Nullability == NullabilityKind::NonNull && + !FnRetTy->isRecordType()) { if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && CurCodeDecl && CurCodeDecl->getAttr())) RetValNullabilityPrecondition = @@ -2361,6 +2363,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { type = cast(ty)->getPointeeType(); break; + case Type::ArrayParameter: case Type::ConstantArray: case Type::IncompleteArray: // Losing element qualification here is fine. diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index afadc29ab1b027..1568b6e6275b9d 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -590,6 +590,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { ResultType = llvm::ArrayType::get(ResultType, 0); break; } + case Type::ArrayParameter: case Type::ConstantArray: { const ConstantArrayType *A = cast(Ty); llvm::Type *EltTy = ConvertTypeForMem(A->getElementType()); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index fd71317572f0c9..18acf7784f714b 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3584,6 +3584,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { case Type::Pipe: llvm_unreachable("Pipe types shouldn't get here"); + case Type::ArrayParameter: + llvm_unreachable("Array Parameter types should not get here."); + case Type::Builtin: case Type::BitInt: // GCC treats vector and complex types as fundamental types. @@ -3868,6 +3871,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: // Itanium C++ ABI 2.9.5p5: // abi::__array_type_info adds no data members to std::type_info. break; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7a53764364ce4d..e6c1767a0082dd 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -49,6 +49,7 @@ #include "ToolChains/WebAssembly.h" #include "ToolChains/XCore.h" #include "ToolChains/ZOS.h" +#include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/TargetID.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" @@ -5814,19 +5815,9 @@ static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA, (C.getArgs().hasArg(options::OPT_fmodule_output) || C.getArgs().hasArg(options::OPT_fmodule_output_EQ))); - if (Arg *ModuleOutputEQ = - C.getArgs().getLastArg(options::OPT_fmodule_output_EQ)) - return C.addResultFile(ModuleOutputEQ->getValue(), &JA); + SmallString<256> OutputPath = + tools::getCXX20NamedModuleOutputPath(C.getArgs(), BaseInput); - SmallString<64> OutputPath; - Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); - if (FinalOutput && C.getArgs().hasArg(options::OPT_c)) - OutputPath = FinalOutput->getValue(); - else - OutputPath = BaseInput; - - const char *Extension = types::getTypeTempSuffix(JA.getType()); - llvm::sys::path::replace_extension(OutputPath, Extension); return C.addResultFile(C.getArgs().MakeArgString(OutputPath.c_str()), &JA); } @@ -5899,6 +5890,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, &JA); } + if (JA.getType() == types::TY_API_INFO && + C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) && + C.getArgs().hasArg(options::OPT_o)) + Diag(clang::diag::err_drv_unexpected_symbol_graph_output) + << C.getArgs().getLastArgValue(options::OPT_o); + // DXC defaults to standard out when generating assembly. We check this after // any DXC flags that might specify a file. if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode()) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3bcacff7724c7d..b7ec7e0a60977b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3839,6 +3839,24 @@ bool Driver::getDefaultModuleCachePath(SmallVectorImpl &Result) { return false; } +llvm::SmallString<256> +clang::driver::tools::getCXX20NamedModuleOutputPath(const ArgList &Args, + const char *BaseInput) { + if (Arg *ModuleOutputEQ = Args.getLastArg(options::OPT_fmodule_output_EQ)) + return StringRef(ModuleOutputEQ->getValue()); + + SmallString<256> OutputPath; + if (Arg *FinalOutput = Args.getLastArg(options::OPT_o); + FinalOutput && Args.hasArg(options::OPT_c)) + OutputPath = FinalOutput->getValue(); + else + OutputPath = BaseInput; + + const char *Extension = types::getTypeTempSuffix(types::TY_ModuleFile); + llvm::sys::path::replace_extension(OutputPath, Extension); + return OutputPath; +} + static bool RenderModulesOptions(Compilation &C, const Driver &D, const ArgList &Args, const InputInfo &Input, const InputInfo &Output, bool HaveStd20, @@ -4027,9 +4045,18 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, // module fragment. CmdArgs.push_back("-fskip-odr-check-in-gmf"); - // Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings. - Args.ClaimAllArgs(options::OPT_fmodule_output); - Args.ClaimAllArgs(options::OPT_fmodule_output_EQ); + // We need to include the case the input file is a module file here. + // Since the default compilation model for C++ module interface unit will + // create temporary module file and compile the temporary module file + // to get the object file. Then the `-fmodule-output` flag will be + // brought to the second compilation process. So we have to claim it for + // the case too. + if (Input.getType() == driver::types::TY_CXXModule || + Input.getType() == driver::types::TY_PP_CXXModule || + Input.getType() == driver::types::TY_ModuleFile) { + Args.ClaimAllArgs(options::OPT_fmodule_output); + Args.ClaimAllArgs(options::OPT_fmodule_output_EQ); + } return HaveModules; } @@ -5019,11 +5046,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, assert(JA.getType() == types::TY_API_INFO && "Extract API actions must generate a API information."); CmdArgs.push_back("-extract-api"); + + if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf)) + PrettySGFArg->render(Args, CmdArgs); + + Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ); + if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ)) ProductNameArg->render(Args, CmdArgs); if (Arg *ExtractAPIIgnoresFileArg = Args.getLastArg(options::OPT_extract_api_ignores_EQ)) ExtractAPIIgnoresFileArg->render(Args, CmdArgs); + if (Arg *EmitExtensionSymbolGraphs = + Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) { + if (!SymbolGraphDirArg) + D.Diag(diag::err_drv_missing_symbol_graph_dir); + + EmitExtensionSymbolGraphs->render(Args, CmdArgs); + } + if (SymbolGraphDirArg) + SymbolGraphDirArg->render(Args, CmdArgs); } else { assert((isa(JA) || isa(JA)) && "Invalid action for clang tool."); diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 0f503c4bd1c4fe..18f6c5ed06a59a 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -193,6 +193,21 @@ DwarfFissionKind getDebugFissionKind(const Driver &D, const llvm::opt::ArgList &Args, llvm::opt::Arg *&Arg); +// Calculate the output path of the module file when compiling a module unit +// with the `-fmodule-output` option or `-fmodule-output=` option specified. +// The behavior is: +// - If `-fmodule-output=` is specfied, then the module file is +// writing to the value. +// - Otherwise if the output object file of the module unit is specified, the +// output path +// of the module file should be the same with the output object file except +// the corresponding suffix. This requires both `-o` and `-c` are specified. +// - Otherwise, the output path of the module file will be the same with the +// input with the corresponding suffix. +llvm::SmallString<256> +getCXX20NamedModuleOutputPath(const llvm::opt::ArgList &Args, + const char *BaseInput); + } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index ace4fb99581e38..62a53b85ce098b 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1075,14 +1075,14 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, /// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the /// LLVM C library for GPUs. -static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args, +static void addOpenMPDeviceLibC(const Compilation &C, const ArgList &Args, ArgStringList &CmdArgs) { if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc)) return; // Check the resource directory for the LLVM libc GPU declarations. If it's // found we can assume that LLVM was built with support for the GPU libc. - SmallString<256> LibCDecls(TC.getDriver().ResourceDir); + SmallString<256> LibCDecls(C.getDriver().ResourceDir); llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers", "llvm-libc-decls"); bool HasLibC = llvm::sys::fs::exists(LibCDecls) && @@ -1090,38 +1090,23 @@ static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args, if (!Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC)) return; - // We don't have access to the offloading toolchains here, so determine from - // the arguments if we have any active NVPTX or AMDGPU toolchains. - llvm::DenseSet Libraries; - if (const Arg *Targets = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { - if (llvm::any_of(Targets->getValues(), - [](auto S) { return llvm::Triple(S).isAMDGPU(); })) { - Libraries.insert("-lcgpu-amdgpu"); - Libraries.insert("-lmgpu-amdgpu"); - } - if (llvm::any_of(Targets->getValues(), - [](auto S) { return llvm::Triple(S).isNVPTX(); })) { - Libraries.insert("-lcgpu-nvptx"); - Libraries.insert("-lmgpu-nvptx"); - } - } + SmallVector ToolChains; + auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP); + for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI) + ToolChains.push_back(TI->second); - for (StringRef Arch : Args.getAllArgValues(options::OPT_offload_arch_EQ)) { - if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) { - return IsAMDGpuArch(StringToCudaArch(Str)); - })) { - Libraries.insert("-lcgpu-amdgpu"); - Libraries.insert("-lmgpu-amdgpu"); - } - if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) { - return IsNVIDIAGpuArch(StringToCudaArch(Str)); - })) { - Libraries.insert("-lcgpu-nvptx"); - Libraries.insert("-lmgpu-nvptx"); - } + if (llvm::any_of(ToolChains, [](const ToolChain *TC) { + return TC->getTriple().isAMDGPU(); + })) { + CmdArgs.push_back("-lcgpu-amdgpu"); + CmdArgs.push_back("-lmgpu-amdgpu"); + } + if (llvm::any_of(ToolChains, [](const ToolChain *TC) { + return TC->getTriple().isNVPTX(); + })) { + CmdArgs.push_back("-lcgpu-nvptx"); + CmdArgs.push_back("-lmgpu-nvptx"); } - - llvm::append_range(CmdArgs, Libraries); } void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, @@ -1153,9 +1138,10 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } } -bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args, bool ForceStaticHostRuntime, - bool IsOffloadingHost, bool GompNeedsRT) { +bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs, + const ToolChain &TC, const ArgList &Args, + bool ForceStaticHostRuntime, bool IsOffloadingHost, + bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) return false; @@ -1196,7 +1182,7 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, CmdArgs.push_back("-lomptarget.devicertl"); if (IsOffloadingHost) - addOpenMPDeviceLibC(TC, Args, CmdArgs); + addOpenMPDeviceLibC(C, Args, CmdArgs); addArchSpecificRPath(TC, Args, CmdArgs); addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index bb37be4bd6ea05..5581905db31144 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -111,8 +111,8 @@ void addOpenMPRuntimeLibraryPath(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); /// Returns true, if an OpenMP runtime has been added. -bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, - const llvm::opt::ArgList &Args, +bool addOpenMPRuntime(const Compilation &C, llvm::opt::ArgStringList &CmdArgs, + const ToolChain &TC, const llvm::opt::ArgList &Args, bool ForceStaticHostRuntime = false, bool IsOffloadingHost = false, bool GompNeedsRT = false); diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index c7682c7f1d3379..caf6c4a444fdce 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -686,7 +686,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) - addOpenMPRuntime(CmdArgs, getToolChain(), Args); + addOpenMPRuntime(C, CmdArgs, getToolChain(), Args); if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp index b59a172bd6ae86..1dbc46763c1156 100644 --- a/clang/lib/Driver/ToolChains/DragonFly.cpp +++ b/clang/lib/Driver/ToolChains/DragonFly.cpp @@ -136,7 +136,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index c5757ddebb0f3e..a8ee6540001ee4 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -295,7 +295,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Args.hasArg(options::OPT_static); - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index a9c9d2475809d7..dedbfac6cb25d2 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -598,7 +598,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. - if (addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP, + if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP, JA.isHostOffloading(Action::OFK_OpenMP), /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp index 30464e2229e65b..346652a7e4bd8e 100644 --- a/clang/lib/Driver/ToolChains/Haiku.cpp +++ b/clang/lib/Driver/ToolChains/Haiku.cpp @@ -107,7 +107,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp index 0eec8fddabd5db..d54f2288294949 100644 --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -311,7 +311,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 6da6728585df93..e20d9fb1cfc417 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -221,7 +221,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp index 5d7f0ae2a392a6..7126e018ca5b6f 100644 --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -211,7 +211,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Args.hasArg(options::OPT_static); - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 22f2c47e1d6a13..81797c8c4dc75a 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1000,6 +1000,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_LValueToRValue: case CK_NoOp: case CK_UserDefinedConversion: + case CK_HLSLArrayRValue: break; case CK_IntegralCast: { diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index aa7a1e9360f474..5a62c5deb24083 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -13,514 +13,67 @@ //===----------------------------------------------------------------------===// #include "clang/ExtractAPI/API.h" -#include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/CommentLexer.h" #include "clang/AST/RawCommentList.h" +#include "clang/Basic/Module.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" #include using namespace clang::extractapi; using namespace llvm; -namespace { +SymbolReference::SymbolReference(const APIRecord *R) + : Name(R->Name), USR(R->USR), Record(R) {} -template -RecordTy *addTopLevelRecord(DenseMap &USRLookupTable, - APISet::RecordMap &RecordMap, - StringRef USR, CtorArgsTy &&...CtorArgs) { - auto Result = RecordMap.insert({USR, nullptr}); - - // Create the record if it does not already exist - if (Result.second) - Result.first->second = - std::make_unique(USR, std::forward(CtorArgs)...); - - auto *Record = Result.first->second.get(); - USRLookupTable.insert({USR, Record}); - return Record; -} - -} // namespace - -NamespaceRecord * -APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader) { - auto *Record = addTopLevelRecord( - USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability), - Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader); - - if (Parent) - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - return Record; -} - -GlobalVariableRecord * -APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Fragments, - DeclarationFragments SubHeading, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc, - std::move(Availability), Linkage, Comment, Fragments, - SubHeading, IsFromSystemHeader); -} - -GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR, - Name, Loc, std::move(Availability), Linkage, Comment, - Declaration, SubHeading, Template, - IsFromSystemHeader); -} - -GlobalFunctionRecord *APISet::addGlobalFunction( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Fragments, - DeclarationFragments SubHeading, FunctionSignature Signature, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc, - std::move(Availability), Linkage, Comment, Fragments, - SubHeading, Signature, IsFromSystemHeader); -} - -GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - Template Template, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR, - Name, Loc, std::move(Availability), Linkage, Comment, - Declaration, SubHeading, Signature, Template, - IsFromSystemHeader); -} - -GlobalFunctionTemplateSpecializationRecord * -APISet::addGlobalFunctionTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - bool IsFromSystemHeader) { - return addTopLevelRecord( - USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name, - Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, - Signature, IsFromSystemHeader); -} - -EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name, - StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader) { - auto Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading, - IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Enum->USR, Enum->Name, Enum->getKind(), Enum); - USRBasedLookupTable.insert({USR, Record.get()}); - return Enum->Constants.emplace_back(std::move(Record)).get(); -} - -EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, IsFromSystemHeader); -} - -RecordFieldRecord *APISet::addRecordField( - RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - APIRecord::RecordKind Kind, bool IsFromSystemHeader) { - auto RecordField = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading, - Kind, IsFromSystemHeader); - RecordField->ParentInformation = APIRecord::HierarchyInformation( - Record->USR, Record->Name, Record->getKind(), Record); - USRBasedLookupTable.insert({USR, RecordField.get()}); - return Record->Fields.emplace_back(std::move(RecordField)).get(); -} - -RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - APIRecord::RecordKind Kind, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Kind, IsFromSystemHeader); -} - -StaticFieldRecord * -APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, SymbolReference Context, - AccessControl Access, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc, - std::move(Availability), Linkage, Comment, - Declaration, SubHeading, Context, Access, - IsFromSystemHeader); -} - -CXXFieldRecord * -APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, AccessControl Access, - bool IsFromSystemHeader) { - auto *Record = addTopLevelRecord( - USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability), - Comment, Declaration, SubHeading, Access, IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass); - return Record; -} - -CXXFieldTemplateRecord *APISet::addCXXFieldTemplate( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - AccessControl Access, Template Template, bool IsFromSystemHeader) { - auto *Record = - addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Access, Template, IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - - return Record; -} - -CXXClassRecord * -APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, APIRecord::RecordKind Kind, - AccessControl Access, bool IsFromSystemHeader) { - auto *Record = addTopLevelRecord( - USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability), - Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader); - if (Parent) - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - return Record; -} - -ClassTemplateRecord *APISet::addClassTemplate( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, AccessControl Access, bool IsFromSystemHeader) { - auto *Record = - addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Template, Access, IsFromSystemHeader); - if (Parent) - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - return Record; -} - -ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - AccessControl Access, bool IsFromSystemHeader) { - auto *Record = - addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR, - Name, Loc, std::move(Availability), Comment, - Declaration, SubHeading, Access, IsFromSystemHeader); - if (Parent) - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - return Record; -} - -ClassTemplatePartialSpecializationRecord * -APISet::addClassTemplatePartialSpecialization( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, AccessControl Access, bool IsFromSystemHeader) { - auto *Record = addTopLevelRecord( - USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc, - std::move(Availability), Comment, Declaration, SubHeading, Template, - Access, IsFromSystemHeader); - if (Parent) - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - return Record; -} - -GlobalVariableTemplateSpecializationRecord * -APISet::addGlobalVariableTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, - GlobalVariableTemplateSpecializations, USR, Name, - Loc, std::move(Availability), Linkage, Comment, - Declaration, SubHeading, IsFromSystemHeader); -} - -GlobalVariableTemplatePartialSpecializationRecord * -APISet::addGlobalVariableTemplatePartialSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader) { - return addTopLevelRecord( - USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR, - Name, Loc, std::move(Availability), Linkage, Comment, Declaration, - SubHeading, Template, IsFromSystemHeader); -} - -ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR, - PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - Template Template, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Template, IsFromSystemHeader); -} - -CXXMethodRecord *APISet::addCXXInstanceMethod( - APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader) { - CXXMethodRecord *Record = - addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); - - Record->ParentInformation = APIRecord::HierarchyInformation( - CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(), - CXXClassRecord); - return Record; -} - -CXXMethodRecord *APISet::addCXXStaticMethod( - APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader) { - CXXMethodRecord *Record = - addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); - - Record->ParentInformation = APIRecord::HierarchyInformation( - CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(), - CXXClassRecord); - return Record; -} - -CXXMethodTemplateRecord *APISet::addCXXMethodTemplate( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, Template Template, - bool IsFromSystemHeader) { - auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR, - Name, Loc, std::move(Availability), Comment, - Declaration, SubHeading, Signature, Access, - Template, IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - - return Record; -} - -CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec( - APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, AccessControl Access, - bool IsFromSystemHeader) { - - auto *Record = addTopLevelRecord( - USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc, - std::move(Availability), Comment, Declaration, SubHeading, Signature, - Access, IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Parent->USR, Parent->Name, Parent->getKind(), Parent); - - return Record; -} - -ObjCCategoryRecord *APISet::addObjCCategory( - StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - SymbolReference Interface, bool IsFromSystemHeader, - bool IsFromExternalModule) { - // Create the category record. - auto *Record = - addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Interface, IsFromSystemHeader); - - Record->IsFromExternalModule = IsFromExternalModule; - - auto It = ObjCInterfaces.find(Interface.USR); - if (It != ObjCInterfaces.end()) - It->second->Categories.push_back(Record); - - return Record; -} - -ObjCInterfaceRecord * -APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, LinkageInfo Linkage, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - SymbolReference SuperClass, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc, - std::move(Availability), Linkage, Comment, - Declaration, SubHeading, SuperClass, - IsFromSystemHeader); -} - -ObjCMethodRecord *APISet::addObjCMethod( - ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, bool IsInstanceMethod, - bool IsFromSystemHeader) { - std::unique_ptr Record; - if (IsInstanceMethod) - Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, IsFromSystemHeader); - else - Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, IsFromSystemHeader); - - Record->ParentInformation = APIRecord::HierarchyInformation( - Container->USR, Container->Name, Container->getKind(), Container); - USRBasedLookupTable.insert({USR, Record.get()}); - return Container->Methods.emplace_back(std::move(Record)).get(); -} - -ObjCPropertyRecord *APISet::addObjCProperty( - ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, - StringRef SetterName, bool IsOptional, bool IsInstanceProperty, - bool IsFromSystemHeader) { - std::unique_ptr Record; - if (IsInstanceProperty) - Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Attributes, GetterName, SetterName, IsOptional, - IsFromSystemHeader); - else - Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Attributes, GetterName, SetterName, IsOptional, - IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Container->USR, Container->Name, Container->getKind(), Container); - USRBasedLookupTable.insert({USR, Record.get()}); - return Container->Properties.emplace_back(std::move(Record)).get(); -} - -ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( - ObjCContainerRecord *Container, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) { - auto Record = std::make_unique( - USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading, - Access, IsFromSystemHeader); - Record->ParentInformation = APIRecord::HierarchyInformation( - Container->USR, Container->Name, Container->getKind(), Container); - USRBasedLookupTable.insert({USR, Record.get()}); - return Container->Ivars.emplace_back(std::move(Record)).get(); +APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) { + switch (Ctx->getKind()) { +#define RECORD_CONTEXT(CLASS, KIND) \ + case KIND: \ + return static_cast(const_cast(Ctx)); +#include "clang/ExtractAPI/APIRecords.inc" + default: + return nullptr; + // llvm_unreachable("RecordContext derived class isn't propertly + // implemented"); + } } -ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR, - PresumedLoc Loc, - AvailabilityInfo Availability, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, IsFromSystemHeader); +RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) { + if (!Record) + return nullptr; + switch (Record->getKind()) { +#define RECORD_CONTEXT(CLASS, KIND) \ + case KIND: \ + return static_cast(const_cast(Record)); +#include "clang/ExtractAPI/APIRecords.inc" + default: + return nullptr; + // llvm_unreachable("RecordContext derived class isn't propertly + // implemented"); + } } -MacroDefinitionRecord * -APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc, - Declaration, SubHeading, IsFromSystemHeader); -} +void RecordContext::addToRecordChain(APIRecord *Record) const { + if (!First) { + First = Record; + Last = Record; + return; + } -TypedefRecord * -APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilityInfo Availability, const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - SymbolReference UnderlyingType, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, UnderlyingType, IsFromSystemHeader); + Last->NextInContext = Record; + Last = Record; } APIRecord *APISet::findRecordForUSR(StringRef USR) const { if (USR.empty()) return nullptr; - return USRBasedLookupTable.lookup(USR); -} - -StringRef APISet::recordUSR(const Decl *D) { - SmallString<128> USR; - index::generateUSRForDecl(D, USR); - return copyString(USR); -} + auto FindIt = USRBasedLookupTable.find(USR); + if (FindIt != USRBasedLookupTable.end()) + return FindIt->getSecond().get(); -StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL, - const SourceManager &SM) { - SmallString<128> USR; - index::generateUSRForMacro(Name, SL, SM, USR); - return copyString(USR); + return nullptr; } StringRef APISet::copyString(StringRef String) { @@ -528,15 +81,22 @@ StringRef APISet::copyString(StringRef String) { return {}; // No need to allocate memory and copy if the string has already been stored. - if (StringAllocator.identifyObject(String.data())) + if (Allocator.identifyObject(String.data())) return String; - void *Ptr = StringAllocator.Allocate(String.size(), 1); + void *Ptr = Allocator.Allocate(String.size(), 1); memcpy(Ptr, String.data(), String.size()); return StringRef(reinterpret_cast(Ptr), String.size()); } +SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR, + StringRef Source) { + return SymbolReference(copyString(Name), copyString(USR), copyString(Source)); +} + APIRecord::~APIRecord() {} +RecordRecord::~RecordRecord() {} +RecordFieldRecord::~RecordFieldRecord() {} ObjCContainerRecord::~ObjCContainerRecord() {} ObjCMethodRecord::~ObjCMethodRecord() {} ObjCPropertyRecord::~ObjCPropertyRecord() {} @@ -546,8 +106,10 @@ void GlobalFunctionRecord::anchor() {} void GlobalVariableRecord::anchor() {} void EnumConstantRecord::anchor() {} void EnumRecord::anchor() {} -void RecordFieldRecord::anchor() {} -void RecordRecord::anchor() {} +void StructFieldRecord::anchor() {} +void StructRecord::anchor() {} +void UnionFieldRecord::anchor() {} +void UnionRecord::anchor() {} void CXXFieldRecord::anchor() {} void CXXClassRecord::anchor() {} void CXXConstructorRecord::anchor() {} diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 80a0a498dc4001..0a243120b7c0e3 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -14,14 +14,11 @@ #include "clang/ExtractAPI/DeclarationFragments.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/QualTypeNames.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "clang/Basic/OperatorKinds.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" -#include using namespace clang::extractapi; using namespace llvm; @@ -60,23 +57,44 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, } // namespace -DeclarationFragments &DeclarationFragments::appendSpace() { +DeclarationFragments & +DeclarationFragments::appendUnduplicatedTextCharacter(char Character) { if (!Fragments.empty()) { Fragment &Last = Fragments.back(); if (Last.Kind == FragmentKind::Text) { // Merge the extra space into the last fragment if the last fragment is // also text. - if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. - Last.Spelling.push_back(' '); + if (Last.Spelling.back() != Character) { // avoid duplicates at end + Last.Spelling.push_back(Character); } } else { - append(" ", FragmentKind::Text); + append("", FragmentKind::Text); + Fragments.back().Spelling.push_back(Character); } } return *this; } +DeclarationFragments &DeclarationFragments::appendSpace() { + return appendUnduplicatedTextCharacter(' '); +} + +DeclarationFragments &DeclarationFragments::appendSemicolon() { + return appendUnduplicatedTextCharacter(';'); +} + +DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() { + if (Fragments.empty()) + return *this; + + Fragment &Last = Fragments.back(); + if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';') + Last.Spelling.pop_back(); + + return *this; +} + StringRef DeclarationFragments::getFragmentKindString( DeclarationFragments::FragmentKind Kind) { switch (Kind) { @@ -469,7 +487,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( if (!Decl->isAnonymousNamespace()) Fragments.appendSpace().append( Decl->getName(), DeclarationFragments::FragmentKind::Identifier); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments @@ -511,7 +529,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { return Fragments .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) .append(std::move(After)) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -535,15 +553,13 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { getFragmentsForType(T, Var->getASTContext(), After); if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), - ArgumentFragment.begin()->Spelling); + std::string ProperArgName = T.getAsString(); ArgumentFragment.begin()->Spelling.swap(ProperArgName); } Fragments.append(std::move(ArgumentFragment)) .appendSpace() .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); return Fragments; } @@ -570,12 +586,7 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { if (StringRef(TypeFragments.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - dyn_cast(Param->getDeclContext()) - ->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - TypeFragments.begin()->Spelling); + std::string ProperArgName = Param->getOriginalType().getAsString(); TypeFragments.begin()->Spelling.swap(ProperArgName); } @@ -668,11 +679,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); if (StringRef(ReturnValueFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = - getNameForTemplateArgument(Func->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - ReturnValueFragment.begin()->Spelling); + std::string ProperArgName = Func->getReturnType().getAsString(); ReturnValueFragment.begin()->Spelling.swap(ProperArgName); } @@ -712,7 +719,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { Fragments.append(DeclarationFragments::getExceptionSpecificationString( Func->getExceptionSpecType())); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( @@ -741,7 +748,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) .append(std::move(After)); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments @@ -757,7 +764,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { .appendSpace() .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) .append(std::move(After)) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl( @@ -775,7 +782,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl( Fragments.appendSpace().append( Record->getName(), DeclarationFragments::FragmentKind::Identifier); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( @@ -790,7 +797,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( Fragments.appendSpace().append( Record->getName(), DeclarationFragments::FragmentKind::Identifier); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments @@ -820,7 +827,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( Fragments.append(DeclarationFragments::getExceptionSpecificationString( Method->getExceptionSpecType())); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( @@ -860,7 +867,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( Fragments.append(DeclarationFragments::getExceptionSpecificationString( Method->getExceptionSpecType())); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments @@ -891,7 +898,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction( Fragments.appendSpace().append("const", DeclarationFragments::FragmentKind::Keyword); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments @@ -923,7 +930,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( Fragments.append(DeclarationFragments::getExceptionSpecificationString( Method->getExceptionSpecType())); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } // Get fragments for template parameters, e.g. T in tempalte ... @@ -961,25 +968,6 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( return Fragments; } -// Find the name of a template argument from the template's parameters. -std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( - const ArrayRef TemplateParameters, std::string TypeParameter) { - // The arg is a generic parameter from a partial spec, e.g. - // T in template Foo. - // - // Those names appear as "type-parameter--", so we must find its - // name from the template's parameter list. - for (unsigned i = 0; i < TemplateParameters.size(); ++i) { - const auto *Parameter = - dyn_cast(TemplateParameters[i]); - if (TypeParameter.compare("type-parameter-" + - std::to_string(Parameter->getDepth()) + "-" + - std::to_string(Parameter->getIndex())) == 0) - return std::string(TemplateParameters[i]->getName()); - } - llvm_unreachable("Could not find the name of a template argument."); -} - // Get fragments for template arguments, e.g. int in template // Foo; // @@ -989,7 +977,7 @@ std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( const ArrayRef TemplateArguments, ASTContext &Context, - const std::optional> TemplateParameters) { + const std::optional> TemplateArgumentLocs) { DeclarationFragments Fragments; for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { if (i) @@ -1003,8 +991,10 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - TemplateParameters.value(), ArgumentFragment.begin()->Spelling); + std::string ProperArgName = TemplateArgumentLocs.value()[i] + .getTypeSourceInfo() + ->getType() + .getAsString(); ArgumentFragment.begin()->Spelling.swap(ProperArgName); } Fragments.append(std::move(ArgumentFragment)); @@ -1028,7 +1018,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( .appendSpace() .append(Concept->getName().str(), DeclarationFragments::FragmentKind::Identifier) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -1069,7 +1059,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), Decl->getASTContext(), std::nullopt)) .append(">", DeclarationFragments::FragmentKind::Text) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -1089,9 +1079,9 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateArguments( Decl->getTemplateArgs().asArray(), Decl->getASTContext(), - Decl->getTemplateParameters()->asArray())) + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -1110,7 +1100,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), Decl->getASTContext(), std::nullopt)) .append(">", DeclarationFragments::FragmentKind::Text) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -1130,9 +1120,9 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateArguments( Decl->getTemplateArgs().asArray(), Decl->getASTContext(), - Decl->getTemplateParameters()->asArray())) + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments @@ -1203,7 +1193,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) .appendSpace() - .append(Category->getClassInterface()->getName(), + .append(Interface->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, Interface) .append(" (", DeclarationFragments::FragmentKind::Text) @@ -1277,7 +1267,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( Fragments.append(getFragmentsForParam(Param)); } - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( @@ -1378,7 +1368,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( .append(Property->getName(), DeclarationFragments::FragmentKind::Identifier) .append(std::move(After)) - .append(";", DeclarationFragments::FragmentKind::Text); + .appendSemicolon(); } DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( @@ -1422,7 +1412,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( .appendSpace() .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); - return Fragments.append(";", DeclarationFragments::FragmentKind::Text); + return Fragments.appendSemicolon(); } // Instantiate template for FunctionDecl. diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 275f49be22e15a..d6335854cbf262 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -30,6 +30,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Index/USRGeneration.h" #include "clang/InstallAPI/HeaderFile.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PPCallbacks.h" @@ -39,6 +40,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" @@ -327,11 +329,12 @@ class MacroCallback : public PPCallbacks { StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName(); PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation()); - StringRef USR = - API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM); + SmallString<128> USR; + index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM, + USR); - API.addMacroDefinition( - Name, USR, Loc, + API.createRecord( + USR, Name, SymbolReference(), Loc, DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD), DeclarationFragmentsBuilder::getSubHeadingForMacro(Name), SM.isInSystemHeader(PM.MacroNameToken.getLocation())); @@ -372,40 +375,57 @@ class APIMacroCallback : public MacroCallback { LocationFileChecker &LCF; }; +std::unique_ptr +createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) { + auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir; + + SmallString<256> FileName; + llvm::sys::path::append(FileName, OutputDirectory, + BaseName + ".symbols.json"); + return CI.createOutputFile( + FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false, + /*UseTemporary*/ true, /*CreateMissingDirectories*/ true); +} + } // namespace -void ExtractAPIActionBase::ImplEndSourceFileAction() { - if (!OS) - return; +void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) { + SymbolGraphSerializerOption SerializationOptions; + SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs; + SerializationOptions.EmitSymbolLabelsForTesting = + CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting; + + if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) { + auto ConstructOutputFile = [&CI](Twine BaseName) { + return createAdditionalSymbolGraphFile(CI, BaseName); + }; + + SymbolGraphSerializer::serializeWithExtensionGraphs( + *OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions); + } else { + SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList, + SerializationOptions); + } - // Setup a SymbolGraphSerializer to write out collected API information in - // the Symbol Graph format. - // FIXME: Make the kind of APISerializer configurable. - SymbolGraphSerializer SGSerializer(*API, IgnoresList); - SGSerializer.serialize(*OS); + // Flush the stream and close the main output stream. OS.reset(); } -std::unique_ptr -ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { - std::unique_ptr OS; - OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile, - /*Extension=*/"json", - /*RemoveFileOnSignal=*/false); - if (!OS) - return nullptr; - return OS; -} - std::unique_ptr ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - OS = CreateOutputFile(CI, InFile); + auto ProductName = CI.getFrontendOpts().ProductName; + + if (CI.getFrontendOpts().SymbolGraphOutputDir.empty()) + OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile, + /*Extension*/ "symbols.json", + /*RemoveFileOnSignal*/ false, + /*CreateMissingDirectories*/ true); + else + OS = createAdditionalSymbolGraphFile(CI, ProductName); if (!OS) return nullptr; - auto ProductName = CI.getFrontendOpts().ProductName; - // Now that we have enough information about the language options and the // target triple, let's create the APISet before anyone uses it. API = std::make_unique( @@ -495,7 +515,9 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) { return true; } -void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); } +void ExtractAPIAction::EndSourceFileAction() { + ImplEndSourceFileAction(getCompilerInstance()); +} std::unique_ptr WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, @@ -506,11 +528,9 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, CreatedASTConsumer = true; - OS = CreateOutputFile(CI, InFile); - if (!OS) - return nullptr; - - auto ProductName = CI.getFrontendOpts().ProductName; + ProductName = CI.getFrontendOpts().ProductName; + auto InputFilename = llvm::sys::path::filename(InFile); + OS = createAdditionalSymbolGraphFile(CI, InputFilename); // Now that we have enough information about the language options and the // target triple, let's create the APISet before anyone uses it. @@ -552,32 +572,6 @@ void WrappingExtractAPIAction::EndSourceFileAction() { WrapperFrontendAction::EndSourceFileAction(); if (CreatedASTConsumer) { - ImplEndSourceFileAction(); + ImplEndSourceFileAction(getCompilerInstance()); } } - -std::unique_ptr -WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI, - StringRef InFile) { - std::unique_ptr OS; - std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir; - - // The symbol graphs need to be generated as a side effect of regular - // compilation so the output should be dumped in the directory provided with - // the command line option. - llvm::SmallString<128> OutFilePath(OutputDir); - auto Seperator = llvm::sys::path::get_separator(); - auto Infilename = llvm::sys::path::filename(InFile); - OutFilePath.append({Seperator, Infilename}); - llvm::sys::path::replace_extension(OutFilePath, "json"); - // StringRef outputFilePathref = *OutFilePath; - - // don't use the default output file - OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false, - /*RemoveFileOnSignal=*/true, - /*UseTemporary=*/true, - /*CreateMissingDirectories=*/true); - if (!OS) - return nullptr; - return OS; -} diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 545860acb7db80..57f966c8b2be35 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -14,13 +14,17 @@ #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Version.h" +#include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/DeclarationFragments.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Path.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/Support/raw_ostream.h" +#include #include #include @@ -33,26 +37,27 @@ namespace { /// Helper function to inject a JSON object \p Obj into another object \p Paren /// at position \p Key. -void serializeObject(Object &Paren, StringRef Key, std::optional Obj) { +void serializeObject(Object &Paren, StringRef Key, + std::optional &&Obj) { if (Obj) Paren[Key] = std::move(*Obj); } -/// Helper function to inject a StringRef \p String into an object \p Paren at -/// position \p Key -void serializeString(Object &Paren, StringRef Key, - std::optional String) { - if (String) - Paren[Key] = std::move(*String); -} - /// Helper function to inject a JSON array \p Array into object \p Paren at /// position \p Key. -void serializeArray(Object &Paren, StringRef Key, std::optional Array) { +void serializeArray(Object &Paren, StringRef Key, + std::optional &&Array) { if (Array) Paren[Key] = std::move(*Array); } +/// Helper function to inject a JSON array composed of the values in \p C into +/// object \p Paren at position \p Key. +template +void serializeArray(Object &Paren, StringRef Key, ContainerTy &&C) { + Paren[Key] = Array(C); +} + /// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version /// format. /// @@ -248,6 +253,7 @@ std::optional serializeDocComment(const DocComment &Comment) { return std::nullopt; Object DocComment; + Array LinesArray; for (const auto &CommentLine : Comment) { Object Line; @@ -256,7 +262,8 @@ std::optional serializeDocComment(const DocComment &Comment) { serializeSourceRange(CommentLine.Begin, CommentLine.End)); LinesArray.emplace_back(std::move(Line)); } - serializeArray(DocComment, "lines", LinesArray); + + serializeArray(DocComment, "lines", std::move(LinesArray)); return DocComment; } @@ -322,19 +329,14 @@ serializeDeclarationFragments(const DeclarationFragments &DF) { /// - \c subHeading : An array of declaration fragments that provides tags, /// and potentially more tokens (for example the \c +/- symbol for /// Objective-C methods). Can be used as sub-headings for documentation. -Object serializeNames(const APIRecord &Record) { +Object serializeNames(const APIRecord *Record) { Object Names; - if (auto *CategoryRecord = - dyn_cast_or_null(&Record)) - Names["title"] = - (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str(); - else - Names["title"] = Record.Name; + Names["title"] = Record->Name; serializeArray(Names, "subHeading", - serializeDeclarationFragments(Record.SubHeading)); + serializeDeclarationFragments(Record->SubHeading)); DeclarationFragments NavigatorFragments; - NavigatorFragments.append(Record.Name, + NavigatorFragments.append(Record->Name, DeclarationFragments::FragmentKind::Identifier, /*PreciseIdentifier*/ ""); serializeArray(Names, "navigator", @@ -351,7 +353,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { Object Kind; switch (RK) { case APIRecord::RK_Unknown: - llvm_unreachable("Records should have an explicit kind"); + Kind["identifier"] = AddLangPrefix("unknown"); + Kind["displayName"] = "Unknown"; break; case APIRecord::RK_Namespace: Kind["identifier"] = AddLangPrefix("namespace"); @@ -484,10 +487,6 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { Kind["identifier"] = AddLangPrefix("class.extension"); Kind["displayName"] = "Class Extension"; break; - case APIRecord::RK_ObjCCategoryModule: - Kind["identifier"] = AddLangPrefix("module.extension"); - Kind["displayName"] = "Module Extension"; - break; case APIRecord::RK_ObjCProtocol: Kind["identifier"] = AddLangPrefix("protocol"); Kind["displayName"] = "Protocol"; @@ -500,6 +499,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { Kind["identifier"] = AddLangPrefix("typealias"); Kind["displayName"] = "Type Alias"; break; + default: + llvm_unreachable("API Record with uninstantiable kind"); } return Kind; @@ -514,12 +515,18 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) { return serializeSymbolKind(Record.getKind(), Lang); } +/// Serialize the function signature field, as specified by the +/// Symbol Graph format. +/// +/// The Symbol Graph function signature property contains two arrays. +/// - The \c returns array is the declaration fragments of the return type; +/// - The \c parameters array contains names and declaration fragments of the +/// parameters. template -std::optional -serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) { +void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) { const auto &FS = Record.Signature; if (FS.empty()) - return std::nullopt; + return; Object Signature; serializeArray(Signature, "returns", @@ -537,63 +544,14 @@ serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) { if (!Parameters.empty()) Signature["parameters"] = std::move(Parameters); - return Signature; + serializeObject(Paren, "functionSignature", std::move(Signature)); } template -std::optional -serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::false_type) { - return std::nullopt; -} - -/// Serialize the function signature field, as specified by the -/// Symbol Graph format. -/// -/// The Symbol Graph function signature property contains two arrays. -/// - The \c returns array is the declaration fragments of the return type; -/// - The \c parameters array contains names and declaration fragments of the -/// parameters. -/// -/// \returns \c std::nullopt if \p FS is empty, or an \c Object containing the -/// formatted function signature. -template -void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) { - serializeObject(Paren, "functionSignature", - serializeFunctionSignatureMixinImpl( - Record, has_function_signature())); -} - -template -std::optional serializeAccessMixinImpl(const RecordTy &Record, - std::true_type) { - const auto &AccessControl = Record.Access; - std::string Access; - if (AccessControl.empty()) - return std::nullopt; - Access = AccessControl.getAccess(); - return Access; -} - -template -std::optional serializeAccessMixinImpl(const RecordTy &Record, - std::false_type) { - return std::nullopt; -} - -template -void serializeAccessMixin(Object &Paren, const RecordTy &Record) { - auto accessLevel = serializeAccessMixinImpl(Record, has_access()); - if (!accessLevel.has_value()) - accessLevel = "public"; - serializeString(Paren, "accessLevel", accessLevel); -} - -template -std::optional serializeTemplateMixinImpl(const RecordTy &Record, - std::true_type) { +void serializeTemplateMixin(Object &Paren, const RecordTy &Record) { const auto &Template = Record.Templ; if (Template.empty()) - return std::nullopt; + return; Object Generics; Array GenericParameters; @@ -619,97 +577,66 @@ std::optional serializeTemplateMixinImpl(const RecordTy &Record, if (!GenericConstraints.empty()) Generics["constraints"] = std::move(GenericConstraints); - return Generics; -} - -template -std::optional serializeTemplateMixinImpl(const RecordTy &Record, - std::false_type) { - return std::nullopt; + serializeObject(Paren, "swiftGenerics", Generics); } -template -void serializeTemplateMixin(Object &Paren, const RecordTy &Record) { - serializeObject(Paren, "swiftGenerics", - serializeTemplateMixinImpl(Record, has_template())); -} +Array generateParentContexts(const SmallVectorImpl &Parents, + Language Lang) { + Array ParentContexts; -struct PathComponent { - StringRef USR; - StringRef Name; - APIRecord::RecordKind Kind; + for (const auto &Parent : Parents) { + Object Elem; + Elem["usr"] = Parent.USR; + Elem["name"] = Parent.Name; + if (Parent.Record) + Elem["kind"] = + serializeSymbolKind(Parent.Record->getKind(), Lang)["identifier"]; + else + Elem["kind"] = + serializeSymbolKind(APIRecord::RK_Unknown, Lang)["identifier"]; + ParentContexts.emplace_back(std::move(Elem)); + } - PathComponent(StringRef USR, StringRef Name, APIRecord::RecordKind Kind) - : USR(USR), Name(Name), Kind(Kind) {} -}; + return ParentContexts; +} -template -bool generatePathComponents( - const RecordTy &Record, const APISet &API, - function_ref ComponentTransformer) { - SmallVector ReverseComponenents; - ReverseComponenents.emplace_back(Record.USR, Record.Name, Record.getKind()); - const auto *CurrentParent = &Record.ParentInformation; - bool FailedToFindParent = false; - while (CurrentParent && !CurrentParent->empty()) { - PathComponent CurrentParentComponent(CurrentParent->ParentUSR, - CurrentParent->ParentName, - CurrentParent->ParentKind); - - auto *ParentRecord = CurrentParent->ParentRecord; - // Slow path if we don't have a direct reference to the ParentRecord - if (!ParentRecord) - ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR); - - // If the parent is a category extended from internal module then we need to - // pretend this belongs to the associated interface. - if (auto *CategoryRecord = - dyn_cast_or_null(ParentRecord)) { - if (!CategoryRecord->IsFromExternalModule) { - ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR); - CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR, - CategoryRecord->Interface.Name, - APIRecord::RK_ObjCInterface); - } - } - - // The parent record doesn't exist which means the symbol shouldn't be - // treated as part of the current product. - if (!ParentRecord) { - FailedToFindParent = true; - break; - } - - ReverseComponenents.push_back(std::move(CurrentParentComponent)); - CurrentParent = &ParentRecord->ParentInformation; +/// Walk the records parent information in reverse to generate a hierarchy +/// suitable for serialization. +SmallVector +generateHierarchyFromRecord(const APIRecord *Record) { + SmallVector ReverseHierarchy; + for (const auto *Current = Record; Current != nullptr; + Current = Current->Parent.Record) + ReverseHierarchy.emplace_back(Current); + + return SmallVector( + std::make_move_iterator(ReverseHierarchy.rbegin()), + std::make_move_iterator(ReverseHierarchy.rend())); +} + +SymbolReference getHierarchyReference(const APIRecord *Record, + const APISet &API) { + // If the parent is a category extended from internal module then we need to + // pretend this belongs to the associated interface. + if (auto *CategoryRecord = dyn_cast_or_null(Record)) { + return CategoryRecord->Interface; + // FIXME: TODO generate path components correctly for categories extending + // an external module. } - for (const auto &PC : reverse(ReverseComponenents)) - ComponentTransformer(PC); - - return FailedToFindParent; + return SymbolReference(Record); } -Object serializeParentContext(const PathComponent &PC, Language Lang) { - Object ParentContextElem; - ParentContextElem["usr"] = PC.USR; - ParentContextElem["name"] = PC.Name; - ParentContextElem["kind"] = serializeSymbolKind(PC.Kind, Lang)["identifier"]; - return ParentContextElem; -} +} // namespace -template -Array generateParentContexts(const RecordTy &Record, const APISet &API, - Language Lang) { - Array ParentContexts; - generatePathComponents( - Record, API, [Lang, &ParentContexts](const PathComponent &PC) { - ParentContexts.push_back(serializeParentContext(PC, Lang)); - }); +Object *ExtendedModule::addSymbol(Object &&Symbol) { + Symbols.emplace_back(std::move(Symbol)); + return Symbols.back().getAsObject(); +} - return ParentContexts; +void ExtendedModule::addRelationship(Object &&Relationship) { + Relationships.emplace_back(std::move(Relationship)); } -} // namespace /// Defines the format version emitted by SymbolGraphSerializer. const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3}; @@ -722,84 +649,44 @@ Object SymbolGraphSerializer::serializeMetadata() const { return Metadata; } -Object SymbolGraphSerializer::serializeModule() const { +Object +SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName) const { Object Module; - // The user is expected to always pass `--product-name=` on the command line - // to populate this field. - Module["name"] = API.ProductName; + Module["name"] = ModuleName; serializeObject(Module, "platform", serializePlatform(API.getTarget())); return Module; } -bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const { - // Skip explicitly ignored symbols. - if (IgnoresList.shouldIgnore(Record.Name)) +bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const { + if (!Record) return true; // Skip unconditionally unavailable symbols - if (Record.Availability.isUnconditionallyUnavailable()) + if (Record->Availability.isUnconditionallyUnavailable()) return true; // Filter out symbols prefixed with an underscored as they are understood to // be symbols clients should not use. - if (Record.Name.starts_with("_")) + if (Record->Name.starts_with("_")) + return true; + + // Skip explicitly ignored symbols. + if (IgnoresList.shouldIgnore(Record->Name)) return true; return false; } -template -std::optional -SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const { - if (shouldSkip(Record)) - return std::nullopt; - - Object Obj; - serializeObject(Obj, "identifier", - serializeIdentifier(Record, API.getLanguage())); - serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage())); - serializeObject(Obj, "names", serializeNames(Record)); - serializeObject( - Obj, "location", - serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true)); - serializeArray(Obj, "availability", - serializeAvailability(Record.Availability)); - serializeObject(Obj, "docComment", serializeDocComment(Record.Comment)); - serializeArray(Obj, "declarationFragments", - serializeDeclarationFragments(Record.Declaration)); - SmallVector PathComponentsNames; - // If this returns true it indicates that we couldn't find a symbol in the - // hierarchy. - if (generatePathComponents(Record, API, - [&PathComponentsNames](const PathComponent &PC) { - PathComponentsNames.push_back(PC.Name); - })) - return {}; - - serializeArray(Obj, "pathComponents", Array(PathComponentsNames)); +ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() { + if (!ForceEmitToMainModule && ModuleForCurrentSymbol) + return *ModuleForCurrentSymbol; - serializeFunctionSignatureMixin(Obj, Record); - serializeAccessMixin(Obj, Record); - serializeTemplateMixin(Obj, Record); - - return Obj; + return MainModule; } -template -void SymbolGraphSerializer::serializeMembers( - const APIRecord &Record, - const SmallVector> &Members) { - // Members should not be serialized if we aren't recursing. - if (!ShouldRecurse) - return; - for (const auto &Member : Members) { - auto MemberRecord = serializeAPIRecord(*Member); - if (!MemberRecord) - continue; - - Symbols.emplace_back(std::move(*MemberRecord)); - serializeRelationship(RelationshipKind::MemberOf, *Member, Record); - } +Array SymbolGraphSerializer::serializePathComponents( + const APIRecord *Record) const { + return Array(map_range(Hierarchy, [](auto Elt) { return Elt.Name; })); } StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) { @@ -816,6 +703,33 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) { llvm_unreachable("Unhandled relationship kind"); } +void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind, + const SymbolReference &Source, + const SymbolReference &Target, + ExtendedModule &Into) { + Object Relationship; + SmallString<64> TestRelLabel; + if (EmitSymbolLabelsForTesting) { + llvm::raw_svector_ostream OS(TestRelLabel); + OS << SymbolGraphSerializer::getRelationshipString(Kind) << " $ " + << Source.USR << " $ "; + if (Target.USR.empty()) + OS << Target.Name; + else + OS << Target.USR; + Relationship["!testRelLabel"] = TestRelLabel; + } + Relationship["source"] = Source.USR; + Relationship["target"] = Target.USR; + Relationship["targetFallback"] = Target.Name; + Relationship["kind"] = SymbolGraphSerializer::getRelationshipString(Kind); + + if (ForceEmitToMainModule) + MainModule.addRelationship(std::move(Relationship)); + else + Into.addRelationship(std::move(Relationship)); +} + StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) { switch (Kind) { case ConstraintKind::Conformance: @@ -826,430 +740,324 @@ StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) { llvm_unreachable("Unhandled constraint kind"); } -void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind, - SymbolReference Source, - SymbolReference Target) { - Object Relationship; - Relationship["source"] = Source.USR; - Relationship["target"] = Target.USR; - Relationship["targetFallback"] = Target.Name; - Relationship["kind"] = getRelationshipString(Kind); - - Relationships.emplace_back(std::move(Relationship)); -} +void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) { + Object Obj; -void SymbolGraphSerializer::visitNamespaceRecord( - const NamespaceRecord &Record) { - auto Namespace = serializeAPIRecord(Record); - if (!Namespace) - return; - Symbols.emplace_back(std::move(*Namespace)); - if (!Record.ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); -} + // If we need symbol labels for testing emit the USR as the value and the key + // starts with '!'' to ensure it ends up at the top of the object. + if (EmitSymbolLabelsForTesting) + Obj["!testLabel"] = Record->USR; -void SymbolGraphSerializer::visitGlobalFunctionRecord( - const GlobalFunctionRecord &Record) { - auto Obj = serializeAPIRecord(Record); - if (!Obj) - return; + serializeObject(Obj, "identifier", + serializeIdentifier(*Record, API.getLanguage())); + serializeObject(Obj, "kind", serializeSymbolKind(*Record, API.getLanguage())); + serializeObject(Obj, "names", serializeNames(Record)); + serializeObject( + Obj, "location", + serializeSourceLocation(Record->Location, /*IncludeFileURI=*/true)); + serializeArray(Obj, "availability", + serializeAvailability(Record->Availability)); + serializeObject(Obj, "docComment", serializeDocComment(Record->Comment)); + serializeArray(Obj, "declarationFragments", + serializeDeclarationFragments(Record->Declaration)); - Symbols.emplace_back(std::move(*Obj)); -} + Obj["pathComponents"] = serializePathComponents(Record); + Obj["accessLevel"] = Record->Access.getAccess(); -void SymbolGraphSerializer::visitGlobalVariableRecord( - const GlobalVariableRecord &Record) { - auto Obj = serializeAPIRecord(Record); - if (!Obj) - return; + ExtendedModule &Module = getModuleForCurrentSymbol(); + // If the hierarchy has at least one parent and child. + if (Hierarchy.size() >= 2) + serializeRelationship(MemberOf, Hierarchy.back(), + Hierarchy[Hierarchy.size() - 2], Module); - Symbols.emplace_back(std::move(*Obj)); + CurrentSymbol = Module.addSymbol(std::move(Obj)); } -void SymbolGraphSerializer::visitEnumRecord(const EnumRecord &Record) { - auto Enum = serializeAPIRecord(Record); - if (!Enum) - return; - - Symbols.emplace_back(std::move(*Enum)); - serializeMembers(Record, Record.Constants); +bool SymbolGraphSerializer::traverseAPIRecord(const APIRecord *Record) { + if (!Record) + return true; + if (shouldSkip(Record)) + return true; + Hierarchy.push_back(getHierarchyReference(Record, API)); + // Defer traversal mechanics to APISetVisitor base implementation + auto RetVal = Base::traverseAPIRecord(Record); + Hierarchy.pop_back(); + return RetVal; } -void SymbolGraphSerializer::visitRecordRecord(const RecordRecord &Record) { - auto SerializedRecord = serializeAPIRecord(Record); - if (!SerializedRecord) - return; - - Symbols.emplace_back(std::move(*SerializedRecord)); - serializeMembers(Record, Record.Fields); +bool SymbolGraphSerializer::visitAPIRecord(const APIRecord *Record) { + serializeAPIRecord(Record); + return true; } -void SymbolGraphSerializer::visitStaticFieldRecord( - const StaticFieldRecord &Record) { - auto StaticField = serializeAPIRecord(Record); - if (!StaticField) - return; - Symbols.emplace_back(std::move(*StaticField)); - serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context); +bool SymbolGraphSerializer::visitGlobalFunctionRecord( + const GlobalFunctionRecord *Record) { + if (!CurrentSymbol) + return true; + + serializeFunctionSignatureMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) { - auto Class = serializeAPIRecord(Record); - if (!Class) - return; +bool SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*Class)); - for (const auto &Base : Record.Bases) - serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); - if (!Record.ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + for (const auto &Base : Record->Bases) + serializeRelationship(RelationshipKind::InheritsFrom, Record, Base, + getModuleForCurrentSymbol()); + return true; } -void SymbolGraphSerializer::visitClassTemplateRecord( - const ClassTemplateRecord &Record) { - auto Class = serializeAPIRecord(Record); - if (!Class) - return; +bool SymbolGraphSerializer::visitClassTemplateRecord( + const ClassTemplateRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*Class)); - for (const auto &Base : Record.Bases) - serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); - if (!Record.ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitClassTemplateSpecializationRecord( - const ClassTemplateSpecializationRecord &Record) { - auto Class = serializeAPIRecord(Record); - if (!Class) - return; - - Symbols.emplace_back(std::move(*Class)); +bool SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord( + const ClassTemplatePartialSpecializationRecord *Record) { + if (!CurrentSymbol) + return true; - for (const auto &Base : Record.Bases) - serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); - if (!Record.ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord( - const ClassTemplatePartialSpecializationRecord &Record) { - auto Class = serializeAPIRecord(Record); - if (!Class) - return; - - Symbols.emplace_back(std::move(*Class)); +bool SymbolGraphSerializer::visitCXXMethodRecord( + const CXXMethodRecord *Record) { + if (!CurrentSymbol) + return true; - for (const auto &Base : Record.Bases) - serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); - if (!Record.ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeFunctionSignatureMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitCXXInstanceMethodRecord( - const CXXInstanceMethodRecord &Record) { - auto InstanceMethod = serializeAPIRecord(Record); - if (!InstanceMethod) - return; +bool SymbolGraphSerializer::visitCXXMethodTemplateRecord( + const CXXMethodTemplateRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*InstanceMethod)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitCXXStaticMethodRecord( - const CXXStaticMethodRecord &Record) { - auto StaticMethod = serializeAPIRecord(Record); - if (!StaticMethod) - return; +bool SymbolGraphSerializer::visitCXXFieldTemplateRecord( + const CXXFieldTemplateRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*StaticMethod)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitMethodTemplateRecord( - const CXXMethodTemplateRecord &Record) { - if (!ShouldRecurse) - // Ignore child symbols - return; - auto MethodTemplate = serializeAPIRecord(Record); - if (!MethodTemplate) - return; - Symbols.emplace_back(std::move(*MethodTemplate)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); -} +bool SymbolGraphSerializer::visitConceptRecord(const ConceptRecord *Record) { + if (!CurrentSymbol) + return true; -void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord( - const CXXMethodTemplateSpecializationRecord &Record) { - if (!ShouldRecurse) - // Ignore child symbols - return; - auto MethodTemplateSpecialization = serializeAPIRecord(Record); - if (!MethodTemplateSpecialization) - return; - Symbols.emplace_back(std::move(*MethodTemplateSpecialization)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) { - if (!ShouldRecurse) - return; - auto CXXField = serializeAPIRecord(Record); - if (!CXXField) - return; - Symbols.emplace_back(std::move(*CXXField)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); -} +bool SymbolGraphSerializer::visitGlobalVariableTemplateRecord( + const GlobalVariableTemplateRecord *Record) { + if (!CurrentSymbol) + return true; -void SymbolGraphSerializer::visitCXXFieldTemplateRecord( - const CXXFieldTemplateRecord &Record) { - if (!ShouldRecurse) - // Ignore child symbols - return; - auto CXXFieldTemplate = serializeAPIRecord(Record); - if (!CXXFieldTemplate) - return; - Symbols.emplace_back(std::move(*CXXFieldTemplate)); - serializeRelationship(RelationshipKind::MemberOf, Record, - Record.ParentInformation.ParentRecord); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) { - auto Concept = serializeAPIRecord(Record); - if (!Concept) - return; +bool SymbolGraphSerializer:: + visitGlobalVariableTemplatePartialSpecializationRecord( + const GlobalVariableTemplatePartialSpecializationRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*Concept)); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer::visitGlobalVariableTemplateRecord( - const GlobalVariableTemplateRecord &Record) { - auto GlobalVariableTemplate = serializeAPIRecord(Record); - if (!GlobalVariableTemplate) - return; - Symbols.emplace_back(std::move(*GlobalVariableTemplate)); -} +bool SymbolGraphSerializer::visitGlobalFunctionTemplateRecord( + const GlobalFunctionTemplateRecord *Record) { + if (!CurrentSymbol) + return true; -void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord( - const GlobalVariableTemplateSpecializationRecord &Record) { - auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record); - if (!GlobalVariableTemplateSpecialization) - return; - Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization)); + serializeTemplateMixin(*CurrentSymbol, *Record); + return true; } -void SymbolGraphSerializer:: - visitGlobalVariableTemplatePartialSpecializationRecord( - const GlobalVariableTemplatePartialSpecializationRecord &Record) { - auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record); - if (!GlobalVariableTemplatePartialSpecialization) - return; - Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization)); -} +bool SymbolGraphSerializer::visitObjCContainerRecord( + const ObjCContainerRecord *Record) { + if (!CurrentSymbol) + return true; -void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord( - const GlobalFunctionTemplateRecord &Record) { - auto GlobalFunctionTemplate = serializeAPIRecord(Record); - if (!GlobalFunctionTemplate) - return; - Symbols.emplace_back(std::move(*GlobalFunctionTemplate)); -} + for (const auto &Protocol : Record->Protocols) + serializeRelationship(ConformsTo, Record, Protocol, + getModuleForCurrentSymbol()); -void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord( - const GlobalFunctionTemplateSpecializationRecord &Record) { - auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record); - if (!GlobalFunctionTemplateSpecialization) - return; - Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization)); + return true; } -void SymbolGraphSerializer::visitObjCContainerRecord( - const ObjCContainerRecord &Record) { - auto ObjCContainer = serializeAPIRecord(Record); - if (!ObjCContainer) - return; +bool SymbolGraphSerializer::visitObjCInterfaceRecord( + const ObjCInterfaceRecord *Record) { + if (!CurrentSymbol) + return true; - Symbols.emplace_back(std::move(*ObjCContainer)); - - serializeMembers(Record, Record.Ivars); - serializeMembers(Record, Record.Methods); - serializeMembers(Record, Record.Properties); - - for (const auto &Protocol : Record.Protocols) - // Record that Record conforms to Protocol. - serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); - - if (auto *ObjCInterface = dyn_cast(&Record)) { - if (!ObjCInterface->SuperClass.empty()) - // If Record is an Objective-C interface record and it has a super class, - // record that Record is inherited from SuperClass. - serializeRelationship(RelationshipKind::InheritsFrom, Record, - ObjCInterface->SuperClass); - - // Members of categories extending an interface are serialized as members of - // the interface. - for (const auto *Category : ObjCInterface->Categories) { - serializeMembers(Record, Category->Ivars); - serializeMembers(Record, Category->Methods); - serializeMembers(Record, Category->Properties); - - // Surface the protocols of the category to the interface. - for (const auto &Protocol : Category->Protocols) - serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); - } - } + if (!Record->SuperClass.empty()) + serializeRelationship(InheritsFrom, Record, Record->SuperClass, + getModuleForCurrentSymbol()); + return true; } -void SymbolGraphSerializer::visitObjCCategoryRecord( - const ObjCCategoryRecord &Record) { - if (!Record.IsFromExternalModule) - return; - - // Check if the current Category' parent has been visited before, if so skip. - if (!visitedCategories.contains(Record.Interface.Name)) { - visitedCategories.insert(Record.Interface.Name); - Object Obj; - serializeObject(Obj, "identifier", - serializeIdentifier(Record, API.getLanguage())); - serializeObject(Obj, "kind", - serializeSymbolKind(APIRecord::RK_ObjCCategoryModule, - API.getLanguage())); - Obj["accessLevel"] = "public"; - Symbols.emplace_back(std::move(Obj)); - } +bool SymbolGraphSerializer::traverseObjCCategoryRecord( + const ObjCCategoryRecord *Record) { + auto *CurrentModule = ModuleForCurrentSymbol; + if (Record->isExtendingExternalModule()) + ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; - Object Relationship; - Relationship["source"] = Record.USR; - Relationship["target"] = Record.Interface.USR; - Relationship["targetFallback"] = Record.Interface.Name; - Relationship["kind"] = getRelationshipString(RelationshipKind::ExtensionTo); - Relationships.emplace_back(std::move(Relationship)); + if (!walkUpFromObjCCategoryRecord(Record)) + return false; - auto ObjCCategory = serializeAPIRecord(Record); + bool RetVal = traverseRecordContext(Record); + ModuleForCurrentSymbol = CurrentModule; + return RetVal; +} - if (!ObjCCategory) - return; +bool SymbolGraphSerializer::walkUpFromObjCCategoryRecord( + const ObjCCategoryRecord *Record) { + return visitObjCCategoryRecord(Record); +} - Symbols.emplace_back(std::move(*ObjCCategory)); - serializeMembers(Record, Record.Methods); - serializeMembers(Record, Record.Properties); +bool SymbolGraphSerializer::visitObjCCategoryRecord( + const ObjCCategoryRecord *Record) { + // If we need to create a record for the category in the future do so here, + // otherwise everything is set up to pretend that the category is in fact the + // interface it extends. + for (const auto &Protocol : Record->Protocols) + serializeRelationship(ConformsTo, Record->Interface, Protocol, + getModuleForCurrentSymbol()); - // Surface the protocols of the category to the interface. - for (const auto &Protocol : Record.Protocols) - serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); + return true; } -void SymbolGraphSerializer::visitMacroDefinitionRecord( - const MacroDefinitionRecord &Record) { - auto Macro = serializeAPIRecord(Record); +bool SymbolGraphSerializer::visitObjCMethodRecord( + const ObjCMethodRecord *Record) { + if (!CurrentSymbol) + return true; - if (!Macro) - return; + serializeFunctionSignatureMixin(*CurrentSymbol, *Record); + return true; +} - Symbols.emplace_back(std::move(*Macro)); +bool SymbolGraphSerializer::visitObjCInstanceVariableRecord( + const ObjCInstanceVariableRecord *Record) { + // FIXME: serialize ivar access control here. + return true; } -void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) { - switch (Record->getKind()) { - case APIRecord::RK_Unknown: - llvm_unreachable("Records should have a known kind!"); - case APIRecord::RK_GlobalFunction: - visitGlobalFunctionRecord(*cast(Record)); - break; - case APIRecord::RK_GlobalVariable: - visitGlobalVariableRecord(*cast(Record)); - break; - case APIRecord::RK_Enum: - visitEnumRecord(*cast(Record)); - break; - case APIRecord::RK_Struct: - LLVM_FALLTHROUGH; - case APIRecord::RK_Union: - visitRecordRecord(*cast(Record)); - break; - case APIRecord::RK_StaticField: - visitStaticFieldRecord(*cast(Record)); - break; - case APIRecord::RK_CXXClass: - visitCXXClassRecord(*cast(Record)); - break; - case APIRecord::RK_ObjCInterface: - visitObjCContainerRecord(*cast(Record)); - break; - case APIRecord::RK_ObjCProtocol: - visitObjCContainerRecord(*cast(Record)); - break; - case APIRecord::RK_ObjCCategory: - visitObjCCategoryRecord(*cast(Record)); - break; - case APIRecord::RK_MacroDefinition: - visitMacroDefinitionRecord(*cast(Record)); - break; - case APIRecord::RK_Typedef: - visitTypedefRecord(*cast(Record)); - break; - default: - if (auto Obj = serializeAPIRecord(*Record)) { - Symbols.emplace_back(std::move(*Obj)); - auto &ParentInformation = Record->ParentInformation; - if (!ParentInformation.empty()) - serializeRelationship(RelationshipKind::MemberOf, *Record, - *ParentInformation.ParentRecord); - } - break; - } +bool SymbolGraphSerializer::walkUpFromTypedefRecord( + const TypedefRecord *Record) { + // Short-circuit walking up the class hierarchy and handle creating typedef + // symbol objects manually as there are additional symbol dropping rules to + // respect. + return visitTypedefRecord(Record); } -void SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord &Record) { +bool SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord *Record) { // Typedefs of anonymous types have their entries unified with the underlying // type. - bool ShouldDrop = Record.UnderlyingType.Name.empty(); + bool ShouldDrop = Record->UnderlyingType.Name.empty(); // enums declared with `NS_OPTION` have a named enum and a named typedef, with // the same name - ShouldDrop |= (Record.UnderlyingType.Name == Record.Name); + ShouldDrop |= (Record->UnderlyingType.Name == Record->Name); if (ShouldDrop) - return; + return true; - auto Typedef = serializeAPIRecord(Record); - if (!Typedef) - return; + // Create the symbol record if the other symbol droppping rules permit it. + serializeAPIRecord(Record); + if (!CurrentSymbol) + return true; - (*Typedef)["type"] = Record.UnderlyingType.USR; + (*CurrentSymbol)["type"] = Record->UnderlyingType.USR; - Symbols.emplace_back(std::move(*Typedef)); + return true; } -Object SymbolGraphSerializer::serialize() { - traverseAPISet(); - return serializeCurrentGraph(); +void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) { + switch (Record->getKind()) { + // dispatch to the relevant walkUpFromMethod +#define CONCRETE_RECORD(CLASS, BASE, KIND) \ + case APIRecord::KIND: { \ + walkUpFrom##CLASS(static_cast(Record)); \ + break; \ + } +#include "clang/ExtractAPI/APIRecords.inc" + // otherwise fallback on the only behavior we can implement safely. + case APIRecord::RK_Unknown: + visitAPIRecord(Record); + break; + default: + llvm_unreachable("API Record with uninstantiable kind"); + } } -Object SymbolGraphSerializer::serializeCurrentGraph() { +Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName, + ExtendedModule &&EM) { Object Root; serializeObject(Root, "metadata", serializeMetadata()); - serializeObject(Root, "module", serializeModule()); + serializeObject(Root, "module", serializeModuleObject(ModuleName)); - Root["symbols"] = std::move(Symbols); - Root["relationships"] = std::move(Relationships); + Root["symbols"] = std::move(EM.Symbols); + Root["relationships"] = std::move(EM.Relationships); return Root; } -void SymbolGraphSerializer::serialize(raw_ostream &os) { - Object root = serialize(); +void SymbolGraphSerializer::serializeGraphToStream( + raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName, + ExtendedModule &&EM) { + Object Root = serializeGraph(ModuleName, std::move(EM)); if (Options.Compact) - os << formatv("{0}", Value(std::move(root))) << "\n"; + OS << formatv("{0}", Value(std::move(Root))) << "\n"; else - os << formatv("{0:2}", Value(std::move(root))) << "\n"; + OS << formatv("{0:2}", Value(std::move(Root))) << "\n"; +} + +void SymbolGraphSerializer::serializeMainSymbolGraph( + raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList, + SymbolGraphSerializerOption Options) { + SymbolGraphSerializer Serializer(API, IgnoresList, + Options.EmitSymbolLabelsForTesting); + Serializer.traverseAPISet(); + Serializer.serializeGraphToStream(OS, Options, API.ProductName, + std::move(Serializer.MainModule)); + // FIXME: TODO handle extended modules here +} + +void SymbolGraphSerializer::serializeWithExtensionGraphs( + raw_ostream &MainOutput, const APISet &API, + const APIIgnoresList &IgnoresList, + llvm::function_ref(Twine BaseName)> + CreateOutputStream, + SymbolGraphSerializerOption Options) { + SymbolGraphSerializer Serializer(API, IgnoresList, + Options.EmitSymbolLabelsForTesting); + Serializer.traverseAPISet(); + + Serializer.serializeGraphToStream(MainOutput, Options, API.ProductName, + std::move(Serializer.MainModule)); + + for (auto &ExtensionSGF : Serializer.ExtendedModules) { + if (auto ExtensionOS = + CreateOutputStream(ExtensionSGF.getKey() + "@" + API.ProductName)) + Serializer.serializeGraphToStream(*ExtensionOS, Options, + ExtensionSGF.getKey(), + std::move(ExtensionSGF.getValue())); + } } std::optional @@ -1262,14 +1070,20 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR, Object Root; APIIgnoresList EmptyIgnores; SymbolGraphSerializer Serializer(API, EmptyIgnores, - /*Options.Compact*/ {true}, - /*ShouldRecurse*/ false); + /*EmitSymbolLabelsForTesting*/ false, + /*ForceEmitToMainModule*/ true); + + // Set up serializer parent chain + Serializer.Hierarchy = generateHierarchyFromRecord(Record); + Serializer.serializeSingleRecord(Record); - serializeObject(Root, "symbolGraph", Serializer.serializeCurrentGraph()); + serializeObject(Root, "symbolGraph", + Serializer.serializeGraph(API.ProductName, + std::move(Serializer.MainModule))); Language Lang = API.getLanguage(); serializeArray(Root, "parentContexts", - generateParentContexts(*Record, API, Lang)); + generateParentContexts(Serializer.Hierarchy, Lang)); Array RelatedSymbols; @@ -1287,14 +1101,15 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR, Object RelatedSymbol; RelatedSymbol["usr"] = RelatedRecord->USR; RelatedSymbol["declarationLanguage"] = getLanguageName(Lang); - // TODO: once we record this properly let's serialize it right. - RelatedSymbol["accessLevel"] = "public"; + RelatedSymbol["accessLevel"] = RelatedRecord->Access.getAccess(); RelatedSymbol["filePath"] = RelatedRecord->Location.getFilename(); RelatedSymbol["moduleName"] = API.ProductName; RelatedSymbol["isSystem"] = RelatedRecord->IsFromSystemHeader; serializeArray(RelatedSymbol, "parentContexts", - generateParentContexts(*RelatedRecord, API, Lang)); + generateParentContexts( + generateHierarchyFromRecord(RelatedRecord), Lang)); + RelatedSymbols.push_back(std::move(RelatedSymbol)); } diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp index 3a5f62c9b2e6cc..41e4e0cf1795f9 100644 --- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp +++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" +#include "clang/Basic/Module.h" #include "clang/Index/USRGeneration.h" using namespace clang; @@ -50,17 +51,20 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type, SmallString<128> TypeUSR; const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type); const TypedefType *TypedefTy = Type->getAs(); + StringRef OwningModuleName; if (TypeDecl) { if (!TypedefTy) TypeName = TypeDecl->getName().str(); clang::index::generateUSRForDecl(TypeDecl, TypeUSR); + if (auto *OwningModule = TypeDecl->getImportedOwningModule()) + OwningModuleName = OwningModule->Name; } else { clang::index::generateUSRForType(Type, Context, TypeUSR); } - return {API.copyString(TypeName), API.copyString(TypeUSR)}; + return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName); } std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const { diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 46ed5baaeacead..e41cf2902a6818 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -955,6 +955,8 @@ template <> struct MappingTraits { Style.BreakBeforeTernaryOperators); IO.mapOptional("BreakConstructorInitializers", Style.BreakConstructorInitializers); + IO.mapOptional("BreakFunctionDefinitionParameters", + Style.BreakFunctionDefinitionParameters); IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("BreakTemplateDeclarations", @@ -1465,6 +1467,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; + LLVMStyle.BreakFunctionDefinitionParameters = false; LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; LLVMStyle.BreakStringLiterals = true; LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 2ddcd5259446f6..48b6a9092a8c09 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -574,6 +574,9 @@ struct FormatToken { /// Is optional and can be removed. bool Optional = false; + /// Might be function declaration open/closing paren. + bool MightBeFunctionDeclParen = false; + /// Number of optional braces to be inserted after this token: /// -1: a single left brace /// 0: no braces diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b9144cf55452e2..3e9988d5094554 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1550,6 +1550,7 @@ class AnnotatingParser { (!Previous->isAttribute() && !Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) { Line.MightBeFunctionDecl = true; + Tok->MightBeFunctionDeclParen = true; } } break; @@ -3888,6 +3889,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } else if (ClosingParen) { for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) { + if (Tok->is(TT_CtorInitializerColon)) + break; if (Tok->is(tok::arrow)) { Tok->setType(TT_TrailingReturnArrow); break; @@ -5392,6 +5395,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0) return true; + if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl && + Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen && + Left.ParameterCount > 0) { + return true; + } + if (Style.isCSharp()) { if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) && Style.BraceWrapping.AfterFunction) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f1bd3cd66e97dc..c5bfb8ef1b5607 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3516,7 +3516,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fblocks); if (Opts.ConvergentFunctions && - !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice)) + !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice || + Opts.HLSL)) GenerateArg(Consumer, OPT_fconvergent_functions); if (Opts.NoBuiltin && !Opts.Freestanding) @@ -3914,7 +3915,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) || Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || - Opts.SYCLIsDevice; + Opts.SYCLIsDevice || Opts.HLSL; Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 9b0ef30a14121b..fdf05c3613c956 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -290,8 +290,7 @@ class PrecompilePreambleAction : public ASTFrontendAction { class PrecompilePreambleConsumer : public PCHGenerator { public: - PrecompilePreambleConsumer(PrecompilePreambleAction &Action, - const Preprocessor &PP, + PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef isysroot, std::shared_ptr Buffer) diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 2446aee571f440..f85f0365616f9a 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -181,9 +181,13 @@ CreateFrontendAction(CompilerInstance &CI) { #endif // Wrap the base FE action in an extract api action to generate - // symbol graph as a biproduct of compilation ( enabled with - // --emit-symbol-graph option ) - if (!FEOpts.SymbolGraphOutputDir.empty()) { + // symbol graph as a biproduct of compilation (enabled with + // --emit-symbol-graph option) + if (FEOpts.EmitSymbolGraph) { + if (FEOpts.SymbolGraphOutputDir.empty()) { + CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir); + CI.getFrontendOpts().SymbolGraphOutputDir = "."; + } CI.getCodeGenOpts().ClearASTBeforeBackend = false; Act = std::make_unique(std::move(Act)); } diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index 6476c5107cb5cc..cf3aaa4c6ec931 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -205,10 +205,10 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { const ObjCInterfaceDecl *InterfaceD = D->getClassInterface(); const StringRef InterfaceName = InterfaceD->getName(); - std::pair Category = - Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, - *Access); - recordObjCInstanceVariables(D->getASTContext(), Category.first, InterfaceName, + ObjCCategoryRecord *CategoryRecord = + Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access) + .first; + recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName, D->ivars()); return true; } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 63fe678cbb29e2..861a25dc5103c1 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1502,6 +1502,15 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { } } +void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) { + while (Tok.is(tok::kw__Nullable)) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + auto Kind = Tok.getKind(); + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); + } +} + /// Determine whether the following tokens are valid after a type-specifier /// which could be a standalone declaration. This will conservatively return /// true if there's any doubt, and is appropriate for insert-';' fixits. @@ -1683,15 +1692,21 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParsedAttributes attrs(AttrFactory); // If attributes exist after tag, parse them. - MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); - - // Parse inheritance specifiers. - if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance, - tok::kw___virtual_inheritance)) - ParseMicrosoftInheritanceClassAttributes(attrs); - - // Allow attributes to precede or succeed the inheritance specifiers. - MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); + for (;;) { + MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); + // Parse inheritance specifiers. + if (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) { + ParseMicrosoftInheritanceClassAttributes(attrs); + continue; + } + if (Tok.is(tok::kw__Nullable)) { + ParseNullabilityClassAttributes(attrs); + continue; + } + break; + } // Source location used by FIXIT to insert misplaced // C++11 attributes diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 50e3c39f60919b..07dd2ba0106a4e 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" +#include "clang/Sema/SemaOpenACC.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -777,7 +778,7 @@ bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) { SourceLocation ClauseLoc = ConsumeToken(); bool Result = ParseOpenACCClauseParams(DirKind, Kind); - getActions().ActOnOpenACCClause(Kind, ClauseLoc); + getActions().OpenACC().ActOnClause(Kind, ClauseLoc); return Result; } @@ -1151,7 +1152,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { SourceLocation StartLoc = getCurToken().getLocation(); OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); - getActions().ActOnOpenACCConstruct(DirKind, StartLoc); + getActions().OpenACC().ActOnConstruct(DirKind, StartLoc); // Once we've parsed the construct/directive name, some have additional // specifiers that need to be taken care of. Atomic has an 'atomic-clause' @@ -1223,12 +1224,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); - if (getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind, - DirInfo.StartLoc)) + if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind, + DirInfo.StartLoc)) return nullptr; // TODO OpenACC: Do whatever decl parsing is required here. - return DeclGroupPtrTy::make(getActions().ActOnEndOpenACCDeclDirective()); + return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective()); } // Parse OpenACC Directive on a Statement. @@ -1239,8 +1240,8 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { ConsumeAnnotationToken(); OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); - if (getActions().ActOnStartOpenACCStmtDirective(DirInfo.DirKind, - DirInfo.StartLoc)) + if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind, + DirInfo.StartLoc)) return StmtError(); StmtResult AssocStmt; @@ -1249,10 +1250,10 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); - AssocStmt = getActions().ActOnOpenACCAssociatedStmt(DirInfo.DirKind, - ParseStatement()); + AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind, + ParseStatement()); } - return getActions().ActOnEndOpenACCStmtDirective( + return getActions().OpenACC().ActOnEndStmtDirective( DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, AssocStmt); } diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index 6722878883be8e..ce6211c23218bb 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/SemaInternal.h" diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 72393bea620526..b7e4fc0ac9b5b2 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -43,6 +43,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" #include "clang/Sema/TypoCorrection.h" @@ -196,7 +197,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ThreadSafetyDeclCache(nullptr), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), - Ident_super(nullptr), + Ident_super(nullptr), OpenACCPtr(std::make_unique(*this)), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), MSStructPragmaOn(false), VtorDispStack(LangOpts.getVtorDispMode()), @@ -653,6 +654,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, case CK_FunctionToPointerDecay: case CK_ToVoid: case CK_NonAtomicToAtomic: + case CK_HLSLArrayRValue: break; } } diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 0dcf42e4899713..a5dd158808f26b 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -215,6 +215,18 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { inferGslPointerAttribute(Record, Record); } +void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) { + static llvm::StringSet<> Nullable{ + "auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr", + "coroutine_handle", "function", "move_only_function", + }; + + if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) && + !CRD->hasAttr()) + for (Decl *Redecl : CRD->redecls()) + Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context)); +} + void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc) { PragmaMsStackAction Action = Sema::PSK_Reset; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 11401b6f56c0ea..3dcd18b3afc8b4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -27,6 +27,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/FormatString.h" +#include "clang/AST/IgnoreExpr.h" #include "clang/AST/NSAPI.h" #include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/OperationKinds.h" @@ -7610,6 +7611,14 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// /// Returns true if the value evaluates to null. static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { + // Treat (smart) pointers constructed from nullptr as null, whether we can + // const-evaluate them or not. + // This must happen first: the smart pointer expr might have _Nonnull type! + if (isa( + IgnoreExprNodes(Expr, IgnoreImplicitAsWrittenSingleStep, + IgnoreElidableImplicitConstructorSingleStep))) + return true; + // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability()) { if (*nullability == NullabilityKind::NonNull) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5027deda0d7e09..5c1152896559b5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10124,23 +10124,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); } - if (getLangOpts().CPlusPlus14 && - (NewFD->isDependentContext() || - (isFriend && CurContext->isDependentContext())) && - NewFD->getReturnType()->isUndeducedType()) { - // If the function template is referenced directly (for instance, as a - // member of the current instantiation), pretend it has a dependent type. - // This is not really justified by the standard, but is the only sane - // thing to do. - // FIXME: For a friend function, we have not marked the function as being - // a friend yet, so 'isDependentContext' on the FD doesn't work. - const FunctionProtoType *FPT = - NewFD->getType()->castAs(); - QualType Result = SubstAutoTypeDependent(FPT->getReturnType()); - NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(), - FPT->getExtProtoInfo())); - } - // C++ [dcl.fct.spec]p3: // The inline specifier shall not appear on a block scope function // declaration. @@ -12112,6 +12095,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, CheckConstPureAttributesUsage(*this, NewFD); + // C++ [dcl.spec.auto.general]p12: + // Return type deduction for a templated function with a placeholder in its + // declared type occurs when the definition is instantiated even if the + // function body contains a return statement with a non-type-dependent + // operand. + // + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it is a template-id that is not a + // concept-id and is dependent; or if its terminal name is: + // - [...] + // - associated by name lookup with one or more declarations of member + // functions of a class that is the current instantiation declared with a + // return type that contains a placeholder type, + // - [...] + // + // If this is a templated function with a placeholder in its return type, + // make the placeholder type dependent since it won't be deduced until the + // definition is instantiated. We do this here because it needs to happen + // for implicitly instantiated member functions/member function templates. + if (getLangOpts().CPlusPlus14 && + (NewFD->isDependentContext() && + NewFD->getReturnType()->isUndeducedType())) { + const FunctionProtoType *FPT = + NewFD->getType()->castAs(); + QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType()); + NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(), + FPT->getExtProtoInfo())); + } + // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. @@ -18319,8 +18331,10 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (PrevDecl) mergeDeclAttributes(New, PrevDecl); - if (auto *CXXRD = dyn_cast(New)) + if (auto *CXXRD = dyn_cast(New)) { inferGslOwnerPointerAttribute(CXXRD); + inferNullableClassAttribute(CXXRD); + } // If there's a #pragma GCC visibility in scope, set the visibility of this // record. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f25f3afd0f4af2..8bce04640e748e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5982,6 +5982,20 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D, D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident)); } +static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (AL.isUsedAsTypeAttr()) + return; + + if (auto *CRD = dyn_cast(D); + !CRD || !(CRD->isClass() || CRD->isStruct())) { + S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str) + << AL << AL.isRegularKeywordAttribute() << "classes"; + return; + } + + handleSimpleAttribute(S, D, AL); +} + static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.hasParsedType()) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; @@ -9933,6 +9947,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_UsingIfExists: handleSimpleAttribute(S, D, AL); break; + + case ParsedAttr::AT_TypeNullable: + handleNullableTypeAttr(S, D, AL); + break; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 091fc3e4836b63..80b4257d9d83ed 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -658,8 +658,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); - // lvalue-to-rvalue conversion cannot be applied to function or array types. - if (T->isFunctionType() || T->isArrayType()) + // lvalue-to-rvalue conversion cannot be applied to types that decay to + // pointers (i.e. function or array types). + if (T->canDecayToPointerType()) return E; // We don't want to throw lvalue-to-rvalue casts on top of @@ -4686,6 +4687,9 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::Decayed: T = cast(Ty)->getPointeeType(); break; + case Type::ArrayParameter: + T = cast(Ty)->getElementType(); + break; case Type::Pointer: T = cast(Ty)->getPointeeType(); break; @@ -12908,6 +12912,8 @@ static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) { case CK_IntegralComplexToReal: case CK_IntegralRealToComplex: return ICK_Complex_Real; + case CK_HLSLArrayRValue: + return ICK_HLSL_Array_RValue; } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 51c8e04bee8c31..76bb78aa8b5458 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4416,6 +4416,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, .get(); break; + case ICK_HLSL_Array_RValue: + FromType = Context.getArrayParameterType(FromType); + From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, @@ -4793,6 +4800,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Num_Conversion_Kinds: case ICK_C_Only_Conversion: case ICK_Incompatible_Pointer_Conversion: + case ICK_HLSL_Array_RValue: llvm_unreachable("Improper second standard conversion"); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index dce225a7204da8..e2a1951f1062cb 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6269,7 +6269,10 @@ void InitializationSequence::InitializeFrom(Sema &S, // initializer is a string literal, see 8.5.2. // - Otherwise, if the destination type is an array, the program is // ill-formed. - if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + // - Except in HLSL, where non-decaying array parameters behave like + // non-array types for initialization. + if (DestType->isArrayType() && !DestType->isArrayParameterType()) { + const ArrayType *DestAT = Context.getAsArrayType(DestType); if (Initializer && isa(DestAT)) { SetFailed(FK_VariableLengthArrayHasInitializer); return; @@ -7079,6 +7082,11 @@ PerformConstructorInitialization(Sema &S, hasCopyOrMoveCtorParam(S.Context, getConstructorInfo(Step.Function.FoundDecl)); + // A smart pointer constructed from a nullable pointer is nullable. + if (NumArgs == 1 && !Kind.isExplicitCast()) + S.diagnoseNullableToNonnullConversion( + Entity.getType(), Args.front()->getType(), Kind.getLocation()); + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, Step.Type, Args, Loc, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d3a9c7abd0e944..38237ee578079d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3243,6 +3243,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Pipe: T = cast(T)->getElementType().getTypePtr(); continue; + + // Array parameter types are treated as fundamental types. + case Type::ArrayParameter: + break; } if (Queue.empty()) diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index d3a602d1c382fa..2ac994cac71e19 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -11,14 +11,15 @@ /// //===----------------------------------------------------------------------===// +#include "clang/AST/StmtOpenACC.h" +#include "clang/Sema/SemaOpenACC.h" #include "clang/Basic/DiagnosticSema.h" -#include "clang/Basic/OpenACCKinds.h" #include "clang/Sema/Sema.h" using namespace clang; namespace { -bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, +bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, SourceLocation StartLoc, bool IsStmt) { switch (K) { default: @@ -30,14 +31,21 @@ bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: if (!IsStmt) - return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K; + return S.SemaRef.Diag(StartLoc, diag::err_acc_construct_appertainment) + << K; break; } return false; } } // namespace -bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, +SemaOpenACC::SemaOpenACC(Sema &S) : SemaRef(S) {} + +ASTContext &SemaOpenACC::getASTContext() const { return SemaRef.Context; } +DiagnosticsEngine &SemaOpenACC::getDiagnostics() const { return SemaRef.Diags; } +const LangOptions &SemaOpenACC::getLangOpts() const { return SemaRef.LangOpts; } + +bool SemaOpenACC::ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc) { if (ClauseKind == OpenACCClauseKind::Invalid) return false; @@ -45,9 +53,10 @@ bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, // whatever it can do. This function will eventually need to start returning // some sort of Clause AST type, but for now just return true/false based on // success. - return Diag(StartLoc, diag::warn_acc_clause_unimplemented) << ClauseKind; + return SemaRef.Diag(StartLoc, diag::warn_acc_clause_unimplemented) + << ClauseKind; } -void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, +void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc) { switch (K) { case OpenACCDirectiveKind::Invalid: @@ -63,17 +72,17 @@ void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, // here as these constructs do not take any arguments. break; default: - Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; + SemaRef.Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; break; } } -bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, +bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc) { return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); } -StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, +StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation EndLoc, StmtResult AssocStmt) { @@ -92,7 +101,7 @@ StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, llvm_unreachable("Unhandled case in directive handling?"); } -StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, +StmtResult SemaOpenACC::ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt) { switch (K) { default: @@ -114,9 +123,9 @@ StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, llvm_unreachable("Invalid associated statement application"); } -bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, +bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc) { return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false); } -DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; } +DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 51450e486eaeb4..0c913bc700f4a1 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -160,6 +160,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_C_Conversion_Extension, ICR_Conversion, ICR_Conversion, + ICR_Conversion, }; static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; @@ -201,6 +202,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { "Incompatible pointer conversion", "Fixed point conversion", "HLSL vector truncation", + "Non-decaying array conversion", }; static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds); return Name[Kind]; @@ -2131,8 +2133,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // A glvalue (3.10) of a non-function, non-array type T can // be converted to a prvalue. bool argIsLValue = From->isGLValue(); - if (argIsLValue && - !FromType->isFunctionType() && !FromType->isArrayType() && + if (argIsLValue && !FromType->canDecayToPointerType() && S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; @@ -2147,6 +2148,19 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // is T (C++ 4.1p1). C++ can't get here with class types; in C, we // just strip the qualifiers because they don't matter. FromType = FromType.getUnqualifiedType(); + } else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() && + ToType->isArrayParameterType()) { + // HLSL constant array parameters do not decay, so if the argument is a + // constant array and the parameter is an ArrayParameterType we have special + // handling here. + FromType = S.Context.getArrayParameterType(FromType); + if (S.Context.getCanonicalType(FromType) != + S.Context.getCanonicalType(ToType)) + return false; + + SCS.First = ICK_HLSL_Array_RValue; + SCS.setAllToTypes(ToType); + return true; } else if (FromType->isArrayType()) { // Array-to-pointer conversion (C++ 4.2) SCS.First = ICK_Array_To_Pointer; @@ -6100,6 +6114,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: + case ICK_HLSL_Array_RValue: llvm_unreachable("found a first conversion kind in Second"); case ICK_Function_Conversion: @@ -14811,6 +14826,13 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } } + // Check for nonnull = nullable. + // This won't be caught in the arg's initialization: the parameter to + // the assignment operator is not marked nonnull. + if (Op == OO_Equal) + diagnoseNullableToNonnullConversion(Args[0]->getType(), + Args[1]->getType(), OpLoc); + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { // Best->Access is only meaningful for class members. diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 691857e88beb49..a0339273a0ba35 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -406,8 +406,8 @@ static void CheckForDuplicateLoopAttrs(Sema &S, ArrayRef Attrs) { << *FirstItr; S.Diag((*FirstItr)->getLocation(), diag::note_previous_attribute); } - return; } + return; } static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9cd19d711af4dc..a2b8cc14ca764f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2191,6 +2191,7 @@ DeclResult Sema::CheckClassTemplate( AddPushedVisibilityAttribute(NewClass); inferGslOwnerPointerAttribute(NewClass); + inferNullableClassAttribute(NewClass); if (TUK != TUK_Friend) { // Per C++ [basic.scope.temp]p2, skip the template parameter scopes. @@ -2719,6 +2720,12 @@ SmallVector TemplateParamsReferencedInTemplateArgumentList( return true; } + bool TraverseTemplateName(TemplateName Template) { + if (auto *TD = Template.getAsTemplateDecl()) + MarkAppeared(TD); + return RecursiveASTVisitor::TraverseTemplateName(Template); + } + void MarkAppeared(NamedDecl *ND) { if (TemplateParams.contains(ND)) ReferencedTemplateParams.insert(ND); @@ -6898,6 +6905,11 @@ bool UnnamedLocalNoLinkageFinder::VisitBitIntType(const BitIntType *T) { return false; } +bool UnnamedLocalNoLinkageFinder::VisitArrayParameterType( + const ArrayParameterType *T) { + return VisitConstantArrayType(T); +} + bool UnnamedLocalNoLinkageFinder::VisitDependentBitIntType( const DependentBitIntType *T) { return false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 9a55881f644254..716660244537b8 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2277,6 +2277,7 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::DependentTemplateSpecialization: case Type::PackExpansion: case Type::Pipe: + case Type::ArrayParameter: // No template argument deduction for these types return TemplateDeductionResult::Success; @@ -6355,11 +6356,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::ConstantArray: case Type::IncompleteArray: + case Type::ArrayParameter: MarkUsedTemplateParameters(Ctx, cast(T)->getElementType(), OnlyDeduced, Depth, Used); break; - case Type::Vector: case Type::ExtVector: MarkUsedTemplateParameters(Ctx, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index fd94caa4e1d449..8762744396f4dd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -4717,6 +4717,18 @@ static bool DiagnoseMultipleAddrSpaceAttributes(Sema &S, LangAS ASOld, return false; } +// Whether this is a type broadly expected to have nullability attached. +// These types are affected by `#pragma assume_nonnull`, and missing nullability +// will be diagnosed with -Wnullability-completeness. +static bool shouldHaveNullability(QualType T) { + return T->canHaveNullability(/*ResultIfUnknown=*/false) && + // For now, do not infer/require nullability on C++ smart pointers. + // It's unclear whether the pragma's behavior is useful for C++. + // e.g. treating type-aliases and template-type-parameters differently + // from types of declarations can be surprising. + !isa(T->getCanonicalTypeInternal()); +} + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -4835,8 +4847,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // inner pointers. complainAboutMissingNullability = CAMN_InnerPointers; - if (T->canHaveNullability(/*ResultIfUnknown*/ false) && - !T->getNullability()) { + if (shouldHaveNullability(T) && !T->getNullability()) { // Note that we allow but don't require nullability on dependent types. ++NumPointersRemaining; } @@ -5059,8 +5070,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If the type itself could have nullability but does not, infer pointer // nullability and perform consistency checking. if (S.CodeSynthesisContexts.empty()) { - if (T->canHaveNullability(/*ResultIfUnknown*/ false) && - !T->getNullability()) { + if (shouldHaveNullability(T) && !T->getNullability()) { if (isVaList(T)) { // Record that we've seen a pointer, but do nothing else. if (NumPointersRemaining > 0) @@ -6505,6 +6515,9 @@ namespace { void VisitDecayedTypeLoc(DecayedTypeLoc TL) { llvm_unreachable("decayed type locs not expected here!"); } + void VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + llvm_unreachable("array parameter type locs not expected here!"); + } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { fillAttributedTypeLoc(TL, State); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 80a10647ca5d33..a2568ad0f82cc2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -39,6 +39,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaOpenACC.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" #include @@ -4000,16 +4001,16 @@ class TreeTransform { SourceLocation BeginLoc, SourceLocation EndLoc, StmtResult StrBlock) { - getSema().ActOnOpenACCConstruct(K, BeginLoc); + getSema().OpenACC().ActOnConstruct(K, BeginLoc); // TODO OpenACC: Include clauses. - if (getSema().ActOnStartOpenACCStmtDirective(K, BeginLoc)) + if (getSema().OpenACC().ActOnStartStmtDirective(K, BeginLoc)) return StmtError(); - StrBlock = getSema().ActOnOpenACCAssociatedStmt(K, StrBlock); + StrBlock = getSema().OpenACC().ActOnAssociatedStmt(K, StrBlock); - return getSema().ActOnEndOpenACCStmtDirective(K, BeginLoc, EndLoc, - StrBlock); + return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc, + StrBlock); } private: @@ -5243,6 +5244,23 @@ QualType TreeTransform::TransformDecayedType(TypeLocBuilder &TLB, return Result; } +template +QualType +TreeTransform::TransformArrayParameterType(TypeLocBuilder &TLB, + ArrayParameterTypeLoc TL) { + QualType OriginalType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (OriginalType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + OriginalType != TL.getElementLoc().getType()) + Result = SemaRef.Context.getArrayParameterType(OriginalType); + TLB.push(Result); + // Nothing to set for ArrayParameterTypeLoc. + return Result; +} + template QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 28e8d27fef08c6..9a39e7d3826e7d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6622,17 +6622,17 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { while (NumLocations--) { assert(Idx < Record.size() && "Invalid data, missing pragma diagnostic states"); - SourceLocation Loc = ReadSourceLocation(F, Record[Idx++]); - auto IDAndOffset = SourceMgr.getDecomposedLoc(Loc); - assert(IDAndOffset.first.isValid() && "invalid FileID for transition"); - assert(IDAndOffset.second == 0 && "not a start location for a FileID"); + FileID FID = ReadFileID(F, Record, Idx); + assert(FID.isValid() && "invalid FileID for transition"); + // FIXME: Remove this once we don't need the side-effects. + (void)SourceMgr.getSLocEntryOrNull(FID); unsigned Transitions = Record[Idx++]; // Note that we don't need to set up Parent/ParentOffset here, because // we won't be changing the diagnostic state within imported FileIDs // (other than perhaps appending to the main source file, which has no // parent). - auto &F = Diag.DiagStatesByLoc.Files[IDAndOffset.first]; + auto &F = Diag.DiagStatesByLoc.Files[FID]; F.StateTransitions.reserve(F.StateTransitions.size() + Transitions); for (unsigned I = 0; I != Transitions; ++I) { unsigned Offset = Record[Idx++]; @@ -6810,6 +6810,10 @@ void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocReader::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocReader::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { TL.setExpansionLoc(readSourceLocation()); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 674ed47581dfd3..bbeb6db011646f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1047,30 +1047,22 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberDNLoc = Record.readDeclarationNameLoc(E->MemberDecl->getDeclName()); E->MemberLoc = Record.readSourceLocation(); E->MemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit(); - E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; + E->MemberExprBits.HasQualifier = HasQualifier; + E->MemberExprBits.HasFoundDecl = HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); - if (HasQualifier || HasFoundDecl) { - DeclAccessPair FoundDecl; - if (HasFoundDecl) { - auto *FoundD = Record.readDeclAs(); - auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); - FoundDecl = DeclAccessPair::make(FoundD, AS); - } else { - FoundDecl = DeclAccessPair::make(E->MemberDecl, - E->MemberDecl->getAccess()); - } - E->getTrailingObjects()->FoundDecl = FoundDecl; + if (HasQualifier) + new (E->getTrailingObjects()) + NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc()); - NestedNameSpecifierLoc QualifierLoc; - if (HasQualifier) - QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->getTrailingObjects()->QualifierLoc = - QualifierLoc; + if (HasFoundDecl) { + auto *FoundD = Record.readDeclAs(); + auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); + *E->getTrailingObjects() = DeclAccessPair::make(FoundD, AS); } if (HasTemplateInfo) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1e5734c9c834eb..ba6a8a5e16e4e7 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -318,6 +318,10 @@ void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { addSourceLocation(TL.getCaretLoc()); } @@ -3127,9 +3131,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, continue; ++NumLocations; - SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0); - assert(!Loc.isInvalid() && "start loc for valid FileID is invalid"); - AddSourceLocation(Loc, Record); + AddFileID(FileIDAndFile.first, Record); Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { @@ -4959,38 +4961,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - // Create a lexical update block containing all of the declarations in the - // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - SmallVector NewGlobalKindDeclPairs; - for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } - } - - auto Abv = std::make_shared(); - Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - { - RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; - Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - bytes(NewGlobalKindDeclPairs)); - } - // And a visible updates block for the translation unit. - Abv = std::make_shared(); - Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); - WriteDeclContextVisibleUpdate(TU); - - // If we have any extern "C" names, write out a visible update for them. - if (Context.ExternCContext) - WriteDeclContextVisibleUpdate(Context.ExternCContext); + // Force all top level declarations to be emitted. + for (const auto *D : TU->noload_decls()) + if (!D->isFromASTFile()) + GetDeclRef(D); // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. @@ -5131,33 +5107,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); - RecordData DeclUpdatesOffsetsRecord; - - // Keep writing types, declarations, and declaration update records - // until we've emitted all of them. - Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); - DeclTypesBlockStartOffset = Stream.GetCurrentBitNo(); - WriteTypeAbbrevs(); - WriteDeclAbbrevs(); - do { - WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - } while (!DeclUpdates.empty()); - Stream.ExitBlock(); - - DoneWritingDeclsAndTypes = true; + WriteDeclAndTypes(Context); - // These things can only be done once we've written out decls and types. - WriteTypeDeclOffsets(); - if (!DeclUpdatesOffsetsRecord.empty()) - Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); WriteComments(); @@ -5242,10 +5193,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, if (!DeleteExprsToAnalyze.empty()) Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); - // Write the visible updates to DeclContexts. - for (auto *DC : UpdatedDeclContexts) - WriteDeclContextVisibleUpdate(DC); - if (!WritingModule) { // Write the submodules that were imported, if any. struct ModuleInfo { @@ -5310,6 +5257,72 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, return backpatchSignature(); } +void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { + // Keep writing types, declarations, and declaration update records + // until we've emitted all of them. + RecordData DeclUpdatesOffsetsRecord; + Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); + DeclTypesBlockStartOffset = Stream.GetCurrentBitNo(); + WriteTypeAbbrevs(); + WriteDeclAbbrevs(); + do { + WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); + while (!DeclTypesToEmit.empty()) { + DeclOrType DOT = DeclTypesToEmit.front(); + DeclTypesToEmit.pop(); + if (DOT.isType()) + WriteType(DOT.getType()); + else + WriteDecl(Context, DOT.getDecl()); + } + } while (!DeclUpdates.empty()); + Stream.ExitBlock(); + + DoneWritingDeclsAndTypes = true; + + // These things can only be done once we've written out decls and types. + WriteTypeDeclOffsets(); + if (!DeclUpdatesOffsetsRecord.empty()) + Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + // Create a lexical update block containing all of the declarations in the + // translation unit that do not come from other AST files. + SmallVector NewGlobalKindDeclPairs; + for (const auto *D : TU->noload_decls()) { + if (!D->isFromASTFile()) { + NewGlobalKindDeclPairs.push_back(D->getKind()); + NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); + } + } + + auto Abv = std::make_shared(); + Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; + Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, + bytes(NewGlobalKindDeclPairs)); + + Abv = std::make_shared(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + // And a visible updates block for the translation unit. + WriteDeclContextVisibleUpdate(TU); + + // If we have any extern "C" names, write out a visible update for them. + if (Context.ExternCContext) + WriteDeclContextVisibleUpdate(Context.ExternCContext); + + // Write the visible updates to DeclContexts. + for (auto *DC : UpdatedDeclContexts) + WriteDeclContextVisibleUpdate(DC); +} + void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { if (DeclUpdates.empty()) return; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 7ce48fede383ea..22e190450d3918 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -970,10 +970,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { VisitExpr(E); bool HasQualifier = E->hasQualifier(); - bool HasFoundDecl = - E->hasQualifierOrFoundDecl() && - (E->getFoundDecl().getDecl() != E->getMemberDecl() || - E->getFoundDecl().getAccess() != E->getMemberDecl()->getAccess()); + bool HasFoundDecl = E->hasFoundDecl(); bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo(); unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -995,15 +992,15 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); Record.AddSourceLocation(E->getOperatorLoc()); + if (HasQualifier) + Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); + if (HasFoundDecl) { DeclAccessPair FoundDecl = E->getFoundDecl(); Record.AddDeclRef(FoundDecl.getDecl()); CurrentPackingBits.addBits(FoundDecl.getAccess(), /*BitWidth=*/2); } - if (HasQualifier) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - if (HasTemplateInfo) AddTemplateKWAndArgsInfo(*E->getTrailingObjects(), E->getTrailingObjects()); diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index f54db36d4a0199..2fece29f34487e 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTReader.h" @@ -23,8 +24,8 @@ using namespace clang; PCHGenerator::PCHGenerator( - const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, StringRef isysroot, std::shared_ptr Buffer, + Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, + StringRef isysroot, std::shared_ptr Buffer, ArrayRef> Extensions, bool AllowASTWithErrors, bool IncludeTimestamps, bool BuildingImplicitModule, bool ShouldCacheASTInMemory, @@ -88,7 +89,7 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { return &Writer; } -ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP, +ReducedBMIGenerator::ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile) : PCHGenerator( @@ -101,12 +102,24 @@ ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP, Module *ReducedBMIGenerator::getEmittingModule(ASTContext &Ctx) { Module *M = Ctx.getCurrentNamedModule(); - assert(M->isNamedModuleUnit() && + assert(M && M->isNamedModuleUnit() && "ReducedBMIGenerator should only be used with C++20 Named modules."); return M; } void ReducedBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) { + // We need to do this to make sure the size of reduced BMI not to be larger + // than full BMI. + // + // FIMXE: We'd better to wrap such options to a new class ASTWriterOptions + // since this is not about searching header really. + // FIXME2: We'd better to move the class writing full BMI with reduced BMI. + HeaderSearchOptions &HSOpts = + getPreprocessor().getHeaderSearchInfo().getHeaderSearchOpts(); + HSOpts.ModulesSkipDiagnosticOptions = true; + HSOpts.ModulesSkipHeaderSearchPaths = true; + HSOpts.ModulesSkipPragmaDiagnosticMappings = true; + PCHGenerator::HandleTranslationUnit(Ctx); if (!isComplete()) diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 902c42a2799be4..069e3a633c1214 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1264,15 +1264,10 @@ void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call, if (!E.Init(Desc, Call, C, State)) return; - const llvm::APSInt *PosV = - C.getSValBuilder().getKnownValue(State, Call.getArgSVal(1)); - const llvm::APSInt *WhenceV = - C.getSValBuilder().getKnownValue(State, Call.getArgSVal(2)); - // Bifurcate the state into failed and non-failed. - // Return zero on success, nonzero on error. - ProgramStateRef StateNotFailed, StateFailed; - std::tie(StateFailed, StateNotFailed) = E.makeRetValAndAssumeDual(State, C); + // Return zero on success, -1 on error. + ProgramStateRef StateNotFailed = E.bindReturnValue(State, C, 0); + ProgramStateRef StateFailed = E.bindReturnValue(State, C, -1); // No failure: Reset the state to opened with no error. StateNotFailed = @@ -1282,12 +1277,10 @@ void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call, // At error it is possible that fseek fails but sets none of the error flags. // If fseek failed, assume that the file position becomes indeterminate in any // case. - StreamErrorState NewErrS = ErrorNone | ErrorFError; - // Setting the position to start of file never produces EOF error. - if (!(PosV && *PosV == 0 && WhenceV && *WhenceV == SeekSetVal)) - NewErrS = NewErrS | ErrorFEof; - StateFailed = E.setStreamState(StateFailed, - StreamState::getOpened(Desc, NewErrS, true)); + // It is allowed to set the position beyond the end of the file. EOF error + // should not occur. + StateFailed = E.setStreamState( + StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError, true)); C.addTransition(StateFailed, E.getFailureNoteTag(this, C)); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index c3fc56ac30ee9f..7a900780384a91 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -330,7 +330,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_ConstructorConversion: case CK_UserDefinedConversion: case CK_FunctionToPointerDecay: - case CK_BuiltinFnToFnPtr: { + case CK_BuiltinFnToFnPtr: + case CK_HLSLArrayRValue: { // Copy the SVal of Ex to CastE. ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); diff --git a/clang/lib/Tooling/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt index 91e6cbdcbc44f7..8b4ab0e2129649 100644 --- a/clang/lib/Tooling/CMakeLists.txt +++ b/clang/lib/Tooling/CMakeLists.txt @@ -53,14 +53,16 @@ else() list(APPEND implicitDirs -I ${implicitDir}) endforeach() + setup_host_tool(clang-ast-dump CLANG_AST_DUMP clang_ast_dump_exe clang_ast_dump_target) + include(GetClangResourceDir) get_clang_resource_dir(resource_dir PREFIX ${LLVM_BINARY_DIR}) add_custom_command( COMMENT Generate ASTNodeAPI.json OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json - DEPENDS clang-ast-dump clang-resource-headers + DEPENDS ${clang_ast_dump_target} clang-resource-headers COMMAND - $ + ${clang_ast_dump_exe} # Skip this in debug mode because parsing AST.h is too slow --skip-processing=${skip_expensive_processing} -I ${resource_dir}/include diff --git a/clang/test/Analysis/stream-error.c b/clang/test/Analysis/stream-error.c index 88f7de4234ffb4..7f9116ff401445 100644 --- a/clang/test/Analysis/stream-error.c +++ b/clang/test/Analysis/stream-error.c @@ -365,27 +365,22 @@ void error_fseek(void) { return; int rc = fseek(F, 1, SEEK_SET); if (rc) { + clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} int IsFEof = feof(F), IsFError = ferror(F); - // Get feof or ferror or no error. - clang_analyzer_eval(IsFEof || IsFError); - // expected-warning@-1 {{FALSE}} - // expected-warning@-2 {{TRUE}} - clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} + // Get ferror or no error. + clang_analyzer_eval(IsFError); // expected-warning {{FALSE}} \ + // expected-warning {{TRUE}} + clang_analyzer_eval(IsFEof); // expected-warning {{FALSE}} // Error flags should not change. - if (IsFEof) - clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} - else - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} if (IsFError) - clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} - else - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} } else { - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} // Error flags should not change. - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} } fclose(F); } @@ -396,15 +391,13 @@ void error_fseeko(void) { return; int rc = fseeko(F, 1, SEEK_SET); if (rc) { - int IsFEof = feof(F), IsFError = ferror(F); - // Get feof or ferror or no error. - clang_analyzer_eval(IsFEof || IsFError); - // expected-warning@-1 {{FALSE}} - // expected-warning@-2 {{TRUE}} - clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} + // Get ferror or no error. + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} \ + // expected-warning {{TRUE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} } else { - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} } fclose(F); } @@ -414,7 +407,7 @@ void error_fseek_0(void) { if (!F) return; int rc = fseek(F, 0, SEEK_SET); - if (rc) { + if (rc == -1) { int IsFEof = feof(F), IsFError = ferror(F); // Get ferror or no error, but not feof. clang_analyzer_eval(IsFError); diff --git a/clang/test/Analysis/stream-note.c b/clang/test/Analysis/stream-note.c index f77cd4aa62841d..54ea699f46674e 100644 --- a/clang/test/Analysis/stream-note.c +++ b/clang/test/Analysis/stream-note.c @@ -226,10 +226,39 @@ void check_indeterminate_fseek(void) { return; int Ret = fseek(F, 1, SEEK_SET); // expected-note {{Assuming this stream operation fails}} if (Ret) { // expected-note {{Taking true branch}} \ - // expected-note {{'Ret' is not equal to 0}} + // expected-note {{'Ret' is -1}} char Buf[2]; fwrite(Buf, 1, 2, F); // expected-warning {{might be 'indeterminate'}} \ // expected-note {{might be 'indeterminate'}} } fclose(F); } + +void error_fseek_ftell(void) { + FILE *F = fopen("file", "r"); + if (!F) // expected-note {{Taking false branch}} \ + // expected-note {{'F' is non-null}} + return; + fseek(F, 0, SEEK_END); // expected-note {{Assuming this stream operation fails}} + long size = ftell(F); // expected-warning {{might be 'indeterminate'}} \ + // expected-note {{might be 'indeterminate'}} + if (size == -1) { + fclose(F); + return; + } + if (size == 1) + fprintf(F, "abcd"); + fclose(F); +} + +void error_fseek_read_eof(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + if (fseek(F, 22, SEEK_SET) == -1) { + fclose(F); + return; + } + fgetc(F); // no warning + fclose(F); +} diff --git a/clang/test/C/C11/n1482.c b/clang/test/C/C11/n1482.c new file mode 100644 index 00000000000000..493c7d0a18f109 --- /dev/null +++ b/clang/test/C/C11/n1482.c @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -verify -ffreestanding -std=c11 %s +// expected-no-diagnostics + +/* WG14 N1482: Clang 4 + * Explicit initializers for atomics + * + * NB: We can only test the compile time behavior from the paper, not the + * runtime behavior. + */ + +#include + +#ifndef ATOMIC_BOOL_LOCK_FREE +#error "Missing ATOMIC_BOOL_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR_LOCK_FREE +#error "Missing ATOMIC_CHAR_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR16_T_LOCK_FREE +#error "Missing ATOMIC_CHAR16_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR32_T_LOCK_FREE +#error "Missing ATOMIC_CHAR32_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_WCHAR_T_LOCK_FREE +#error "Missing ATOMIC_WCHAR_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_SHORT_LOCK_FREE +#error "Missing ATOMIC_SHORT_LOCK_FREE" +#endif + +#ifndef ATOMIC_INT_LOCK_FREE +#error "Missing ATOMIC_INT_LOCK_FREE" +#endif + +#ifndef ATOMIC_LONG_LOCK_FREE +#error "Missing ATOMIC_LONG_LOCK_FREE" +#endif + +#ifndef ATOMIC_LLONG_LOCK_FREE +#error "Missing ATOMIC_LLONG_LOCK_FREE" +#endif + +#ifndef ATOMIC_POINTER_LOCK_FREE +#error "Missing ATOMIC_POINTER_LOCK_FREE" +#endif + +#ifndef ATOMIC_VAR_INIT +#error "Missing ATOMIC_VAR_INIT" +#endif + +#ifndef atomic_init +#error "Missing atomic_init" +#endif diff --git a/clang/test/C/C99/float_h-characteristics.c b/clang/test/C/C99/float_h-characteristics.c new file mode 100644 index 00000000000000..7e2a891ef87774 --- /dev/null +++ b/clang/test/C/C99/float_h-characteristics.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify -std=c99 -ffreestanding %s +// RUN: %clang_cc1 -verify -std=gnu89 -ffreestanding %s +// RUN: %clang_cc1 -verify -std=c89 -ffreestanding %s +// expected-no-diagnostics + +/* WG14 ???: Clang 16 + * Additional floating-point characteristics in + * + * NB: the original paper number is unknown, this was gleaned from the editor's + * report in the C99 foreword. There were two new additions to in + * C99, this is testing that we support both of them. + * + * Clang added the macros at least as far back as Clang 3.0, but it wasn't + * until Clang 16.0 that we stopped accidentally providing FLT_EVAL_METHOD in + * C89 (strict) mode. + */ + +#include + +// We expect all the definitions in C99 mode. +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define EXPECT_DECIMAL_DIG +#define EXPECT_FLT_EVAL_METHOD +#endif + +// If we're not in C99 mode, we still expect the definition of DECIMAL_DIG +// unless we're in strict ansi mode. +#if !defined(EXPECT_DECIMAL_DIG) && !defined(__STRICT_ANSI__) +#define EXPECT_DECIMAL_DIG +#endif + +#if defined(EXPECT_DECIMAL_DIG) + #if !defined(DECIMAL_DIG) + #error "DECIMAL_DIG missing" + #endif +#else + #if defined(DECIMAL_DIG) + #error "DECIMAL_DIG provided when not expected" + #endif +#endif + +#if defined(EXPECT_FLT_EVAL_METHOD) + #if !defined(FLT_EVAL_METHOD) + #error "FLT_EVAL_METHOD missing" + #endif +#else + #if defined(FLT_EVAL_METHOD) + #error "FLT_EVAL_METHOD provided when not expected" + #endif +#endif diff --git a/clang/test/C/C99/n570.c b/clang/test/C/C99/n570.c new file mode 100644 index 00000000000000..31c09224e618b5 --- /dev/null +++ b/clang/test/C/C99/n570.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify -std=c99 %s +// RUN: %clang_cc1 -E -std=c99 %s | FileCheck %s +// expected-no-diagnostics + +/* WG14 N570: Yes + * Empty macro arguments + * + * NB: the original paper is not available online anywhere, so the test + * coverage is coming from what could be gleaned from the C99 rationale + * document. In C89, it was UB to pass no arguments to a function-like macro, + * and that's now supported in C99. + */ + +#define TEN 10 +#define U u +#define I // expands into no preprocessing tokens +#define L L +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) + +const unsigned u = xglue(TEN, U); +const int i = xglue(TEN, I); +const long l = xglue(TEN, L); + +// CHECK: const unsigned u = 10u; +// CHECK-NEXT: const int i = 10; +// CHECK-NEXT: const long l = 10L; + +_Static_assert(u == 10U, ""); +_Static_assert(i == 10, ""); +_Static_assert(l == 10L, ""); diff --git a/clang/test/C/C99/n782.c b/clang/test/C/C99/n782.c new file mode 100644 index 00000000000000..d147fd6fb1a1a2 --- /dev/null +++ b/clang/test/C/C99/n782.c @@ -0,0 +1,23 @@ +/* RUN: %clang_cc1 -verify -std=c99 -pedantic %s + RUN: %clang_cc1 -verify=c89 -std=c89 -pedantic %s + expected-no-diagnostics + */ + +/* WG14 N782: Clang 3.4 + * Relaxed constraints on aggregate and union initialization + */ + +void test(void) { + struct S { + int x, y; + }; + int a = 1, b = 2; + struct S s = { a, b }; /* c89-warning {{initializer for aggregate is not a compile-time constant}} */ + + union U { + int x; + float f; + }; + union U u = { a }; /* c89-warning {{initializer for aggregate is not a compile-time constant}} */ +} + diff --git a/clang/test/C/C99/n835.c b/clang/test/C/C99/n835.c new file mode 100644 index 00000000000000..38a974e065724d --- /dev/null +++ b/clang/test/C/C99/n835.c @@ -0,0 +1,35 @@ +/* RUN: %clang_cc1 -verify -pedantic -std=c99 %s + RUN: %clang_cc1 -verify=c89 -pedantic -std=c89 %s + expected-no-diagnostics + */ + +/* WG14 N835: Yes + * Conversion of array to pointer not limited to lvalues + * + * NB: The crux of the change was C99 changing: + * + * C89 3.2.2.1: Except when it is the operand of ..., an lvalue that has type + * 'array of type' is converted to an expression that has type 'pointer to + * type' that points to the initial element of the array object and is not an + * lvalue. + * + * C99 6.3.2.1p3: Except when it is the operand of ..., an expression that has + * type 'array of type' is converted to an expression with type 'pointer to + * type' that points to the initial element of the array object and is not an + * lvalue. + */ + +struct S { + char arr[100]; +}; + +struct S f(void); + +void func(void) { + char c; + /* The return from f() is an rvalue, so this code is not valid in C89, but is + * valid in C99. + */ + c = f().arr[10]; /* c89-warning {{ISO C90 does not allow subscripting non-lvalue array}} */ +} + diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 766c90d3bc7bda..f4d6c04fb8e073 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -35,6 +35,17 @@ void g() { } } // namespace dr1601 +namespace dr1606 { // dr1606: 3.1 +#if __cplusplus >= 201103L + std::size_t test() { + int i = 1; + int j = 1; + auto f = [=]{ return i + j; }; + return sizeof(f); + } +#endif +} // namespace dr1606 + namespace dr1611 { // dr1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; diff --git a/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c b/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c new file mode 100644 index 00000000000000..40d3543d8a6f90 --- /dev/null +++ b/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -triple m68k -emit-llvm -O2 %s -o - | FileCheck %s + +/// Check GCC register names and alias can be used in register variable definition. + +// CHECK-LABEL: @test_d0 +// CHECK: call void asm sideeffect "", "{d0}"(i32 undef) +void test_d0() { + register int a asm ("d0"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d1 +// CHECK: call void asm sideeffect "", "{d1}"(i32 undef) +void test_d1() { + register int a asm ("d1"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d2 +// CHECK: call void asm sideeffect "", "{d2}"(i32 undef) +void test_d2() { + register int a asm ("d2"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d3 +// CHECK: call void asm sideeffect "", "{d3}"(i32 undef) +void test_d3() { + register int a asm ("d3"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d4 +// CHECK: call void asm sideeffect "", "{d4}"(i32 undef) +void test_d4() { + register int a asm ("d4"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d5 +// CHECK: call void asm sideeffect "", "{d5}"(i32 undef) +void test_d5() { + register int a asm ("d5"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d6 +// CHECK: call void asm sideeffect "", "{d6}"(i32 undef) +void test_d6() { + register int a asm ("d6"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d7 +// CHECK: call void asm sideeffect "", "{d7}"(i32 undef) +void test_d7() { + register int a asm ("d7"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a0 +// CHECK: call void asm sideeffect "", "{a0}"(i32 undef) +void test_a0() { + register int a asm ("a0"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a1 +// CHECK: call void asm sideeffect "", "{a1}"(i32 undef) +void test_a1() { + register int a asm ("a1"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a2 +// CHECK: call void asm sideeffect "", "{a2}"(i32 undef) +void test_a2() { + register int a asm ("a2"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a3 +// CHECK: call void asm sideeffect "", "{a3}"(i32 undef) +void test_a3() { + register int a asm ("a3"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a4 +// CHECK: call void asm sideeffect "", "{a4}"(i32 undef) +void test_a4() { + register int a asm ("a4"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a5 +// CHECK: call void asm sideeffect "", "{a5}"(i32 undef) +void test_a5() { + register int a asm ("a5"); + register int b asm ("bp"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); +} + +// CHECK-LABEL: @test_a6 +// CHECK: call void asm sideeffect "", "{a6}"(i32 undef) +void test_a6() { + register int a asm ("a6"); + register int b asm ("fp"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); +} + +// CHECK-LABEL: @test_sp +// CHECK: call void asm sideeffect "", "{sp}"(i32 undef) +void test_sp() { + register int a asm ("sp"); + register int b asm ("usp"); + register int c asm ("ssp"); + register int d asm ("isp"); + register int e asm ("a7"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); + asm ("" :: "r" (c)); + asm ("" :: "r" (d)); + asm ("" :: "r" (e)); +} + +// CHECK-LABEL: @test_pc +// CHECK: call void asm sideeffect "", "{pc}"(i32 undef) +void test_pc() { + register int a asm ("pc"); + asm ("" :: "r" (a)); +} diff --git a/clang/test/CodeGen/atomic.c b/clang/test/CodeGen/atomic.c index af5c056bbfe6e8..16c29e282ddd9f 100644 --- a/clang/test/CodeGen/atomic.c +++ b/clang/test/CodeGen/atomic.c @@ -1,10 +1,14 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=s390x-linux-gnu | FileCheck %s --check-prefixes=CHECK,SYSTEMZ // CHECK: @[[NONSTATIC_GLOB_POINTER_FROM_INT:.+]] = global ptr null // CHECK: @[[GLOB_POINTER:.+]] = internal global ptr null // CHECK: @[[GLOB_POINTER_FROM_INT:.+]] = internal global ptr null // CHECK: @[[GLOB_INT:.+]] = internal global i32 0 // CHECK: @[[GLOB_FLT:.+]] = internal global float {{[0e\+-\.]+}}, align +// CHECK: @[[GLOB_DBL:.+]] = internal global double {{[0e\+-\.]+}}, align +// X86: @[[GLOB_LONGDBL:.+]] = internal global x86_fp80 {{[0xK]+}}, align +// SYSTEMZ: @[[GLOB_LONGDBL:.+]] = internal global fp128 {{[0xL]+}}, align int atomic(void) { // non-sensical test for sync functions @@ -79,8 +83,10 @@ int atomic(void) { // CHECK: atomicrmw nand ptr %valc, i8 6 seq_cst, align 1 __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 - // CHECK: extractvalue { i32, i1 } [[PAIR]], 0 + // X86: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // X86-NEXT: extractvalue { i32, i1 } [[PAIR]], 0 + // SYSTEMZ: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i64 0, i64 0 seq_cst seq_cst, align 8 + // SYSTEMZ-NEXT: extractvalue { i64, i1 } [[PAIR]], 0 if ( __sync_val_compare_and_swap(&valb, 0, 1)) { // CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr %valb, i8 0, i8 1 seq_cst seq_cst, align 1 @@ -90,13 +96,15 @@ int atomic(void) { } __sync_bool_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // X86: cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // SYSTEMZ: cmpxchg ptr null, i64 0, i64 0 seq_cst seq_cst, align 8 __sync_lock_release(&val); // CHECK: store atomic i32 0, {{.*}} release, align 4 __sync_lock_release(&ptrval); - // CHECK: store atomic i32 0, {{.*}} release, align 4 + // X86: store atomic i32 0, {{.*}} release, align 4 + // SYSTEMZ: store atomic i64 0, {{.*}} release, align 8 __sync_synchronize (); // CHECK: fence seq_cst @@ -131,19 +139,25 @@ static _Atomic(int *) glob_pointer_from_int = 0; _Atomic(int *) nonstatic_glob_pointer_from_int = 0LL; static _Atomic int glob_int = 0; static _Atomic float glob_flt = 0.0f; +static _Atomic double glob_dbl = 0.0f; +static _Atomic long double glob_longdbl = 0.0f; void force_global_uses(void) { + // X86: %atomic-temp = alloca x86_fp80, align 16 (void)glob_pointer; - // CHECK: %[[LOCAL_INT:.+]] = load atomic i32, ptr @[[GLOB_POINTER]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT]] to ptr + // CHECK: load atomic ptr, ptr @[[GLOB_POINTER]] seq_cst (void)glob_pointer_from_int; - // CHECK: %[[LOCAL_INT_2:.+]] = load atomic i32, ptr @[[GLOB_POINTER_FROM_INT]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_2]] to ptr + // CHECK-NEXT: load atomic ptr, ptr @[[GLOB_POINTER_FROM_INT]] seq_cst (void)nonstatic_glob_pointer_from_int; - // CHECK: %[[LOCAL_INT_3:.+]] = load atomic i32, ptr @[[NONSTATIC_GLOB_POINTER_FROM_INT]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_3]] to ptr + // CHECK-NEXT: load atomic ptr, ptr @[[NONSTATIC_GLOB_POINTER_FROM_INT]] seq_cst (void)glob_int; - // CHECK: load atomic i32, ptr @[[GLOB_INT]] seq_cst + // CHECK-NEXT: load atomic i32, ptr @[[GLOB_INT]] seq_cst (void)glob_flt; - // CHECK: load atomic float, ptr @[[GLOB_FLT]] seq_cst + // CHECK-NEXT: load atomic float, ptr @[[GLOB_FLT]] seq_cst + (void)glob_dbl; + // CHECK-NEXT: load atomic double, ptr @[[GLOB_DBL]] seq_cst + (void)glob_longdbl; + // X86: call void @__atomic_load(i32 noundef 16, ptr noundef @glob_longdbl, ptr noundef %atomic-temp + // X86-NEXT: %0 = load x86_fp80, ptr %atomic-temp, align 16 + // SYSTEMZ: load atomic fp128, ptr @[[GLOB_LONGDBL]] seq_cst } diff --git a/clang/test/CodeGenCXX/bitfield-access-tail.cpp b/clang/test/CodeGenCXX/bitfield-access-tail.cpp index 68716fdf3b1daa..1539e17cad4369 100644 --- a/clang/test/CodeGenCXX/bitfield-access-tail.cpp +++ b/clang/test/CodeGenCXX/bitfield-access-tail.cpp @@ -2,45 +2,45 @@ // Configs that have cheap unaligned access // Little Endian -// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s // RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s -// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s // Big Endian -// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s // Configs that have expensive unaligned access // Little Endian -// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s // Big endian -// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s -// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s // Can use tail padding struct Pod { @@ -113,3 +113,45 @@ struct __attribute__((packed)) PNonPod { // LAYOUT-DWN32-NEXT: + +struct __attribute__((aligned(4))) Empty {} empty; + +struct Char { char a; } cbase; +struct D : virtual Char { + [[no_unique_address]] Empty e0; + [[no_unique_address]] Empty e1; + unsigned a : 24; // keep as 24bits +} d; +// CHECK-LABEL: LLVMType:%struct.D = +// LAYOUT64-SAME: type <{ ptr, [3 x i8], %struct.Char, [4 x i8] }> +// LAYOUT32-SAME: type { ptr, [3 x i8], %struct.Char } +// LAYOUT-DWN32-SAME: type { ptr, [3 x i8], %struct.Char } +// CHECK-NEXT: NonVirtualBaseLLVMType: +// LAYOUT64-SAME: %struct.D.base = type <{ ptr, i32 }> +// LAYOUT32-SAME: %struct.D = type { ptr, [3 x i8], %struct.Char } +// LAYOUT-DWN32-SAME: %struct.D = type { ptr, [3 x i8], %struct.Char } +// CHECK: BitFields:[ +// LAYOUT-NEXT: + +struct Int { int a; } ibase; +struct E : virtual Int { + [[no_unique_address]] Empty e0; + [[no_unique_address]] Empty e1; + unsigned a : 24; // expand to 32 +} e; +// CHECK-LABEL: LLVMType:%struct.E = +// LAYOUT64-SAME: type <{ ptr, i32, %struct.Int }> +// LAYOUT32-SAME: type { ptr, i32, %struct.Int } +// LAYOUT-DWN32-SAME: type { ptr, i32, %struct.Int } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.E.base = +// LAYOUT64-SAME: type <{ ptr, i32 }> +// LAYOUT32-SAME: type { ptr, i32 } +// LAYOUT-DWN32-SAME: type { ptr, i32 } +// CHECK: BitFields:[ +// LAYOUT-NEXT: diff --git a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl new file mode 100644 index 00000000000000..63a30b61440eb5 --- /dev/null +++ b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +void fn(float x[2]) { } + +// CHECK-LABEL: define void {{.*}}call{{.*}} +// CHECK: [[Arr:%.*]] = alloca [2 x float] +// CHECK: [[Tmp:%.*]] = alloca [2 x float] +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) +// CHECK: call void {{.*}}fn{{.*}}(ptr noundef byval([2 x float]) align 4 [[Tmp]]) +void call() { + float Arr[2] = {0, 0}; + fn(Arr); +} + +struct Obj { + float V; + int X; +}; + +void fn2(Obj O[4]) { } + +// CHECK-LABEL: define void {{.*}}call2{{.*}} +// CHECK: [[Arr:%.*]] = alloca [4 x %struct.Obj] +// CHECK: [[Tmp:%.*]] = alloca [4 x %struct.Obj] +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr]], i8 0, i32 32, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 32, i1 false) +// CHECK: call void {{.*}}fn2{{.*}}(ptr noundef byval([4 x %struct.Obj]) align 4 [[Tmp]]) +void call2() { + Obj Arr[4] = {}; + fn2(Arr); +} + + +void fn3(float x[2][2]) { } + +// CHECK-LABEL: define void {{.*}}call3{{.*}} +// CHECK: [[Arr:%.*]] = alloca [2 x [2 x float]] +// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{.*}}, i32 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 16, i1 false) +// CHECK: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x [2 x float]]) align 4 [[Tmp]]) +void call3() { + float Arr[2][2] = {{0, 0}, {1,1}}; + fn3(Arr); +} + +// CHECK-LABEL: define void {{.*}}call4{{.*}}(ptr +// CHECK-SAME: noundef byval([2 x [2 x float]]) align 4 [[Arr:%.*]]) +// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 16, i1 false) +// CHECK: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x [2 x float]]) align 4 [[Tmp]]) + +void call4(float Arr[2][2]) { + fn3(Arr); +} + +// Verify that each template instantiation codegens to a unique and correctly +// mangled function name. + +// CHECK-LABEL: define void {{.*}}template_call{{.*}}(ptr + +// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]], +// CHECK-SAME: ptr noundef byval([4 x float]) align 4 [[FA4:%[0-9A-Z]+]], +// CHECK-SAME: ptr noundef byval([3 x i32]) align 4 [[IA3:%[0-9A-Z]+]] + +// CHECK: [[Tmp1:%.*]] = alloca [2 x float] +// CHECK: [[Tmp2:%.*]] = alloca [4 x float] +// CHECK: [[Tmp3:%.*]] = alloca [3 x i32] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp1]], ptr align 4 [[FA2]], i32 8, i1 false) +// CHECK: call void @"??$template_fn@$$BY01M@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 [[Tmp1]]) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp2]], ptr align 4 [[FA4]], i32 16, i1 false) +// CHECK: call void @"??$template_fn@$$BY03M@@YAXY03M@Z"(ptr noundef byval([4 x float]) align 4 [[Tmp2]]) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp3]], ptr align 4 [[IA3]], i32 12, i1 false) +// CHECK: call void @"??$template_fn@$$BY02H@@YAXY02H@Z"(ptr noundef byval([3 x i32]) align 4 [[Tmp3]]) + +template +void template_fn(T Val) {} + +void template_call(float FA2[2], float FA4[4], int IA3[3]) { + template_fn(FA2); + template_fn(FA4); + template_fn(IA3); +} + + +// Verify that Array parameter element access correctly codegens. +// CHECK-LABEL: define void {{.*}}element_access{{.*}}(ptr +// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]] + +// CHECK: [[Addr:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 0 +// CHECK: [[Tmp:%.*]] = load float, ptr [[Addr]] +// CHECK: call void @"??$template_fn@M@@YAXM@Z"(float noundef [[Tmp]]) + +// CHECK: [[Idx0:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 0 +// CHECK: [[Val0:%.*]] = load float, ptr [[Idx0]] +// CHECK: [[Sum:%.*]] = fadd float [[Val0]], 5.000000e+00 +// CHECK: [[Idx1:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 1 +// CHECK: store float [[Sum]], ptr [[Idx1]] + +void element_access(float FA2[2]) { + template_fn(FA2[0]); + FA2[1] = FA2[0] + 5; +} diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl index 379c8f118f52f3..6ea80d692cd244 100644 --- a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl @@ -12,7 +12,7 @@ uint test_1() { // CHECK: define spir_func noundef i32 @_Z6test_2v() [[A0]] { // CHECK: %[[C2:[0-9]+]] = call token @llvm.experimental.convergence.entry() -// CHECK: call spir_func noundef i32 @_Z6test_1v() [ "convergencectrl"(token %[[C2]]) ] +// CHECK: call spir_func noundef i32 @_Z6test_1v() {{#[0-9]+}} [ "convergencectrl"(token %[[C2]]) ] uint test_2() { return test_1(); } diff --git a/clang/test/CodeGenHLSL/convergent-functions.hlsl b/clang/test/CodeGenHLSL/convergent-functions.hlsl new file mode 100644 index 00000000000000..f7c8b642272b1e --- /dev/null +++ b/clang/test/CodeGenHLSL/convergent-functions.hlsl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.4-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +void fn() { +}; + +// CHECK: define{{.*| }}void {{.*}}fn{{.*}}() +// CHECK-SAME: #[[Attr:[0-9]+]] +// CHECK: attributes #[[Attr]] = { {{[^}]*}}convergent{{[^}]*}} } diff --git a/clang/test/Driver/Inputs/in.so b/clang/test/Driver/Inputs/in.so deleted file mode 100644 index 8b137891791fe9..00000000000000 --- a/clang/test/Driver/Inputs/in.so +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc b/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc deleted file mode 100644 index 8b137891791fe9..00000000000000 --- a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc b/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc deleted file mode 100644 index 8b137891791fe9..00000000000000 --- a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/empty.o b/clang/test/Driver/Inputs/openmp_static_device_link/empty.o deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc b/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc deleted file mode 100644 index 1a87fd836dba2c..00000000000000 Binary files a/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc and /dev/null differ diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/libFatArchive.a b/clang/test/Driver/Inputs/openmp_static_device_link/libFatArchive.a deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index 07ff43642a62be..4d58f0fb548b57 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -301,5 +301,8 @@ // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Foa.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1 %s // RELATIVE_OBJPATH1: "-object-file-name=a.obj" +// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo:a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s +// RELATIVE_OBJPATH1_COLON: "-object-file-name=a.obj" + // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fofoo/a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH2 %s // RELATIVE_OBJPATH2: "-object-file-name=foo\\a.obj" diff --git a/clang/test/Driver/compiler-rt-unwind.c b/clang/test/Driver/compiler-rt-unwind.c index 4260dab9302c78..7f4e3f22ab19ae 100644 --- a/clang/test/Driver/compiler-rt-unwind.c +++ b/clang/test/Driver/compiler-rt-unwind.c @@ -3,7 +3,7 @@ // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC %s // RTLIB-GCC: "-lgcc" // RTLIB-GCC-SAME: "--as-needed" @@ -12,7 +12,7 @@ // // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GXX %s // RTLIB-GXX: "-lgcc" // RTLIB-GXX-NOT: "--as-needed" @@ -21,11 +21,11 @@ // // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s // RUN: not %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-UNWINDLIB-COMPILER-RT: "-lgcc" // RTLIB-GCC-UNWINDLIB-COMPILER-RT-SAME: "--as-needed" @@ -35,7 +35,7 @@ // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ // RUN: -shared-libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT: "-l:libunwind.so" // RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT-SAME: "-lgcc" @@ -43,24 +43,24 @@ // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT: "-lgcc" // RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT %s // RTLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT-SAME: "--as-needed" @@ -69,21 +69,21 @@ // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC %s // RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-GCC-SAME: "-lgcc_s" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -// RUN: -static --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -static -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC %s // RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC-SAME: "-lgcc_eh" // // RUN: not %clang %s 2> %t.err \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: FileCheck --input-file=%t.err --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER_RT %s // RTLIB-GCC-UNWINDLIB-COMPILER_RT: "{{[.|\\\n]*}}--rtlib=libgcc requires --unwindlib=libgcc" // @@ -97,7 +97,6 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ // RUN: -shared-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.dll.a" @@ -105,18 +104,15 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT-SAME: "-lunwind" diff --git a/clang/test/Driver/constructors.c b/clang/test/Driver/constructors.c index 1cb3aec840c2d9..570b6ec94617f2 100644 --- a/clang/test/Driver/constructors.c +++ b/clang/test/Driver/constructors.c @@ -7,58 +7,49 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fno-use-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-NO-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fno-use-init-array -fuse-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fuse-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm-unknown-linux-androideabi \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-android \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=aarch64-none-linux-gnu \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ @@ -68,7 +59,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm64-none-linux-gnu \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ diff --git a/clang/test/Driver/cuda-detect.cu b/clang/test/Driver/cuda-detect.cu index 49e58004e672c3..67af470018ff96 100644 --- a/clang/test/Driver/cuda-detect.cu +++ b/clang/test/Driver/cuda-detect.cu @@ -146,8 +146,8 @@ // Verify that C++ include paths are passed for both host and device frontends. // RUN: %clang -### --target=x86_64-linux-gnu %s \ -// RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \ -// RUN: -nogpulib -nogpuinc --gcc-toolchain="" 2>&1 \ +// RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \ +// RUN: -nogpulib -nogpuinc 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE // Verify that CUDA SDK version is propagated to the CC1 compilations. diff --git a/clang/test/Driver/dragonfly.c b/clang/test/Driver/dragonfly.c index 931f23f6f57b5f..33c4e4c77eac5e 100644 --- a/clang/test/Driver/dragonfly.c +++ b/clang/test/Driver/dragonfly.c @@ -5,7 +5,6 @@ // Check x86_64-unknown-dragonfly, X86_64 // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-dragonfly \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_dragonfly_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X86_64 %s // CHECK-LD-X86_64: "-cc1" "-triple" "x86_64-unknown-dragonfly" diff --git a/clang/test/Driver/env.c b/clang/test/Driver/env.c index 40a42dc9618576..3f56c7fdae9022 100644 --- a/clang/test/Driver/env.c +++ b/clang/test/Driver/env.c @@ -8,13 +8,13 @@ // RUN: %clang %s -### -o %t.o --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=platform --unwindlib=platform -no-pie \ -// RUN: --gcc-toolchain="" 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s // // RUN: env -i LC_ALL=C PATH="" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" CLANG_NO_DEFAULT_CONFIG=1 \ // RUN: %clang %s -### -o %t.o --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=platform --unwindlib=platform -no-pie \ -// RUN: --gcc-toolchain="" 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s // // CHECK-LD-32-NOT: warning: // CHECK-LD-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" diff --git a/clang/test/Driver/haiku.c b/clang/test/Driver/haiku.c index 060a56b3c70e56..3f421ab6e81e68 100644 --- a/clang/test/Driver/haiku.c +++ b/clang/test/Driver/haiku.c @@ -39,7 +39,6 @@ // Check x86_64-unknown-haiku, X86_64 // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-haiku \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X86_64 %s // CHECK-LD-X86_64: "-cc1" "-triple" "x86_64-unknown-haiku" @@ -63,7 +62,6 @@ // Check the right flags are present with -shared // RUN: %clang -### %s -shared 2>&1 --target=x86_64-unknown-haiku \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ // RUN: | FileCheck --check-prefix=CHECK-X86_64-SHARED %s // CHECK-X86_64-SHARED: "-cc1" "-triple" "x86_64-unknown-haiku" diff --git a/clang/test/Driver/hexagon-toolchain-elf.c b/clang/test/Driver/hexagon-toolchain-elf.c index da859a144cfc88..ac921547266c95 100644 --- a/clang/test/Driver/hexagon-toolchain-elf.c +++ b/clang/test/Driver/hexagon-toolchain-elf.c @@ -36,7 +36,6 @@ // RUN: %clangxx -### --target=hexagon-unknown-elf -fno-integrated-as \ // RUN: -ccc-install-dir %S/Inputs/hexagon_tree/qc/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -nostdlibinc %s 2>&1 | FileCheck -check-prefix=CHECK113 %s // CHECK113: "-cc1" // CHECK113-NOT: "-internal-isystem" diff --git a/clang/test/Driver/hip-link-shared-library.hip b/clang/test/Driver/hip-link-shared-library.hip index 73643682dda8ae..a075ee82dda1cb 100644 --- a/clang/test/Driver/hip-link-shared-library.hip +++ b/clang/test/Driver/hip-link-shared-library.hip @@ -1,6 +1,7 @@ // RUN: touch %t.o +// RUN: touch %t.so // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \ -// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %S/Inputs/in.so \ +// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %t.so \ // RUN: --no-offload-new-driver -fgpu-rdc 2>&1 | FileCheck %s // CHECK: # "x86_64-unknown-linux-gnu" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[HOSTOBJ:.*o]]", "{{.*o}}", "{{.*o}}"] @@ -11,4 +12,4 @@ // CHECK-NOT: offload bundler // CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[IMG1]]", "[[IMG2]]"], output: "[[FATBINOBJ:.*o]]" // CHECK-NOT: offload bundler -// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "{{.*}}/Inputs/in.so", "[[FATBINOBJ]]"], output: "a.out" +// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "{{.*}}.so", "[[FATBINOBJ]]"], output: "a.out" diff --git a/clang/test/Driver/linux-header-search.cpp b/clang/test/Driver/linux-header-search.cpp index dd4d6eb483a3fb..70a85deac89e40 100644 --- a/clang/test/Driver/linux-header-search.cpp +++ b/clang/test/Driver/linux-header-search.cpp @@ -9,7 +9,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s // CHECK-BASIC-LIBCXX-SYSROOT: "-cc1" // CHECK-BASIC-LIBCXX-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -24,7 +23,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" @@ -38,7 +36,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s // CHECK-BASIC-LIBCXX-INSTALL: "-cc1" // CHECK-BASIC-LIBCXX-INSTALL: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -52,7 +49,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-SYSROOT %s // CHECK-BASIC-LIBCXXV2-SYSROOT: "-cc1" // CHECK-BASIC-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -65,7 +61,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxxv2_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-INSTALL %s // CHECK-BASIC-LIBCXXV2-INSTALL: "-cc1" // CHECK-BASIC-LIBCXXV2-INSTALL: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -80,7 +75,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" @@ -93,7 +87,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT %s // CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-cc1" // CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -106,7 +99,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.6.2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-6-2 %s // CHECK-GENTOO-4-6-2: "-cc1" // CHECK-GENTOO-4-6-2: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -121,7 +113,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.6.4_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-6-4 %s // CHECK-GENTOO-4-6-4: "-cc1" // CHECK-GENTOO-4-6-4: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -136,7 +127,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.3_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s // CHECK-GENTOO-4-9-3: "-cc1" // CHECK-GENTOO-4-9-3: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -155,14 +145,12 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s // // Test that gcc-config support does not break multilib. // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-X32 %s // CHECK-GENTOO-4-9-3-X32: "-cc1" // CHECK-GENTOO-4-9-3-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -178,7 +166,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-32 %s // CHECK-GENTOO-4-9-3-32: "-cc1" // CHECK-GENTOO-4-9-3-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -198,7 +185,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X %s // // CHECK-GENTOO-4-9-X: "-cc1" @@ -215,7 +201,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-X32 %s // CHECK-GENTOO-4-9-X-X32: "-cc1" // CHECK-GENTOO-4-9-X-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -231,7 +216,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-32 %s // CHECK-GENTOO-4-9-X-32: "-cc1" // CHECK-GENTOO-4-9-X-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -248,14 +232,12 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=loongarch64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LOONG64-GNU %s // // Check that "-gnuf64" is seen as "-gnu" for loong64. // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=loongarch64-unknown-linux-gnuf64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LOONG64-GNU %s // CHECK-LOONG64-GNU: "-cc1" // CHECK-LOONG64-GNU: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -274,7 +256,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=mips64-unknown-linux-gnuabi64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64-GNUABI %s // CHECK-MIPS64-GNUABI: "-cc1" // CHECK-MIPS64-GNUABI: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -292,7 +273,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=mips64el-unknown-linux-gnuabi64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-GNUABI %s // CHECK-MIPS64EL-GNUABI: "-cc1" // CHECK-MIPS64EL-GNUABI: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -311,7 +291,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm-oe-linux-gnueabi -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s // CHECK-OE-ARM: "-cc1" @@ -323,7 +302,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=aarch64-oe-linux -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s // CHECK-OE-AARCH64: "-cc1" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index d77367b4ece7b9..4020b138dc8fde 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -4,7 +4,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s // CHECK-LD-32-NOT: warning: @@ -17,7 +16,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64 %s // CHECK-LD-64-NOT: warning: @@ -36,7 +34,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s // CHECK-LD-X32-NOT: warning: @@ -51,7 +48,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT %s @@ -74,7 +70,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-unknown-linux \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT-I686 %s @@ -96,7 +91,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT-ANDROID %s @@ -111,7 +105,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-GCC %s // CHECK-LD-GCC-NOT: warning: @@ -131,7 +124,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC-LIBGCC %s // CHECK-LD-64-STATIC-LIBGCC-NOT: warning: @@ -150,7 +142,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC %s // CHECK-CLANG-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -160,7 +151,6 @@ // // RUN: %clangxx -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANGXX-NO-LIBGCC %s // CHECK-CLANGXX-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -170,7 +160,6 @@ // // RUN: %clang -static -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-STATIC %s // CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -178,7 +167,6 @@ // // RUN: %clang -static-pie -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE %s // CHECK-CLANG-LD-STATIC-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -189,7 +177,6 @@ // // RUN: not %clang -static-pie -pie -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-PIE %s // CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -200,7 +187,6 @@ // // RUN: not %clang -static-pie -static -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-STATIC %s // CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -211,14 +197,12 @@ // // RUN: not %clang -static-pie -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-NOPIE %s // CHECK-CLANG-LD-STATIC-PIE-NOPIE: error: cannot specify 'nopie' along with 'static-pie' // // RUN: %clang -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-DYNAMIC %s // CHECK-CLANG-NO-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -228,7 +212,6 @@ // // RUN: %clang -static-libgcc -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC %s // CHECK-CLANG-STATIC-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -238,7 +221,6 @@ // // RUN: %clang -static-libgcc -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC-DYNAMIC %s // CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -248,7 +230,6 @@ // // RUN: %clang -shared-libgcc -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC %s // CHECK-CLANG-SHARED-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -258,7 +239,6 @@ // // RUN: %clang -shared-libgcc -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC-DYNAMIC %s // CHECK-CLANG-SHARED-LIBGCC-DYNAMIC: "-lgcc_s" "-lgcc" @@ -267,7 +247,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-NONE %s // CHECK-CLANG-ANDROID-NONE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -275,7 +254,6 @@ // // RUN: %clang -shared -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-SHARED %s // CHECK-CLANG-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -283,7 +261,6 @@ // // RUN: %clang -static -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-STATIC %s // CHECK-CLANG-ANDROID-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -292,7 +269,6 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC %s // CHECK-LD-64-STATIC-NOT: warning: @@ -309,7 +285,7 @@ // CHECK-LD-64-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // RUN: %clang -no-pie -### %s --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -shared -static \ -// RUN: --gcc-toolchain= --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s +// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s // CHECK-LD-SHARED-STATIC: "-shared" "-static" // CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtbeginS.o" // CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtendS.o" @@ -318,13 +294,11 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static-libgcc -static \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC %s // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_32bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-32 %s // CHECK-32-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -340,7 +314,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_32bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-64 %s // CHECK-32-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -356,7 +329,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-64 %s // CHECK-64-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -372,7 +344,6 @@ // // RUN: not %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=plaform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-32 %s // CHECK-64-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -388,7 +359,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32 %s // CHECK-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -404,7 +374,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -mx32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-X32 %s // CHECK-64-TO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -420,7 +389,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -mx32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-X32 %s // CHECK-32-TO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -436,7 +404,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32-TO-64 %s // CHECK-X32-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -452,7 +419,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32-TO-32 %s // CHECK-X32-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -484,7 +450,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m32 \ // RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing1/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION1 %s // CHECK-GCC-VERSION1: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -496,7 +461,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s @@ -509,7 +473,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s @@ -525,7 +488,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-C-LINK %s // CHECK-BASIC-LIBCXX-C-LINK-NOT: warning: @@ -538,7 +500,6 @@ // Check multi arch support on Ubuntu 12.04 LTS. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s // @@ -547,7 +508,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-musleabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s // CHECK-UBUNTU-12-04-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -563,7 +523,6 @@ // Check Ubuntu 13.10 on x86-64 targeting arm-linux-gnueabihf. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/x86-64_ubuntu_13.10 \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-UBUNTU-13-10-ARM-HF %s // CHECK-X86-64-UBUNTU-13-10-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -582,7 +541,6 @@ // Check Ubuntu 13.10 on x86-64 targeting arm-linux-gnueabi. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/x86-64_ubuntu_13.10 \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-UBUNTU-13-10-ARM %s // CHECK-X86-64-UBUNTU-13-10-ARM: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -601,7 +559,6 @@ // Check Ubuntu 14.04 on powerpc64le. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64le-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-PPC64LE %s // CHECK-UBUNTU-14-04-PPC64LE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -618,7 +575,6 @@ // "/usr/lib/gcc/x86_64-linux-gnu/4.8/x32/crtend.o" "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../libx32/crtn.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-X32 %s // CHECK-UBUNTU-14-04-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -635,7 +591,6 @@ // Check fedora 18 on arm. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_18_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-18-ARM-HF %s // CHECK-FEDORA-18-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -650,12 +605,10 @@ // Check Fedora 21 on AArch64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_21_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-21-AARCH64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_21_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-21-AARCH64 %s // CHECK-FEDORA-21-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -670,7 +623,6 @@ // Check Fedora 31 on riscv64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-redhat-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_31_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-31-RISCV64 %s // CHECK-FEDORA-31-RISCV64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -684,7 +636,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM %s // CHECK-UBUNTU-12-04-ARM: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -700,7 +651,6 @@ // Test the setup that shipped in SUSE 10.3 on ppc64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/suse_10.3_ppc64_tree \ // RUN: | FileCheck --check-prefix=CHECK-SUSE-10-3-PPC64 %s // CHECK-SUSE-10-3-PPC64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -713,12 +663,10 @@ // Check openSuse Leap 42.2 on AArch64 // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s // CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -733,12 +681,10 @@ // Check openSUSE Tumbleweed on armv6hl // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv6hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv6hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s // CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -753,12 +699,10 @@ // Check openSUSE Tumbleweed on armv7hl // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s // CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -773,12 +717,10 @@ // Check openSUSE Tumbleweed on riscv64 // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-RISCV64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-RISCV64 %s // CHECK-OPENSUSE-TW-RISCV64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -793,7 +735,6 @@ // Check openSUSE Tumbleweed on ppc // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_ppc_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-PPC %s // CHECK-OPENSUSE-TW-PPC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1048,32 +989,26 @@ // Test linker invocation on Android. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1090,19 +1025,16 @@ // CHECK-ANDROID: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s @@ -1113,13 +1045,11 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s @@ -1136,7 +1066,6 @@ // CHECK-ANDROID-SO: "{{.*}}{{/|\\\\}}crtend_so.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1147,7 +1076,6 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1158,13 +1086,11 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1180,37 +1106,31 @@ // CHECK-ANDROID-STATIC: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s @@ -1225,32 +1145,26 @@ // CHECK-ANDROID-PIE: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // CHECK-ANDROID-32: "-dynamic-linker" "/system/bin/linker" @@ -1260,13 +1174,11 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: -fsanitize=hwaddress \ // RUN: --target=x86_64-linux-android33 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-OLD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: -fsanitize=hwaddress \ // RUN: --target=x86_64-linux-android34 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-NEW %s // CHECK-ANDROID-OLD: "-dynamic-linker" "/system/bin/linker64" @@ -1275,67 +1187,55 @@ // Test that -pthread does not add -lpthread on Android. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s @@ -1343,20 +1243,19 @@ // // RUN: not %clang %t.o -no-pie -### -o %t 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD-LINK %s // CHECK-ANDROID-PTHREAD-LINK-NOT: argument unused during compilation: '-pthread' /// Check -fandroid-pad-segment. // RUN: %clang -### %s --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -fandroid-pad-segment 2>&1 | FileCheck --check-prefix=CHECK-ANDROID-PAD-PHDR %s // CHECK-ANDROID-PAD-PHDR: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-ANDROID-PAD-PHDR: "[[SYSROOT]]/usr/lib/crtbegin_dynamic.o" "[[SYSROOT]]/usr/lib/crt_pad_segment.o" // RUN: %clang -### %s --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -fandroid-pad-segment -fno-android-pad-segment 2>&1 | FileCheck --check-prefix=CHECK-NO-ANDROID-PAD-PHDR %s // CHECK-NO-ANDROID-PAD-PHDR: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-NO-ANDROID-PAD-PHDR: "[[SYSROOT]]/usr/lib/crtbegin_dynamic.o" @@ -1368,14 +1267,12 @@ // Check linker invocation on a Debian LoongArch sysroot. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=loongarch64-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-LOONG64 %s // // Check that "-gnuf64" is seen as "-gnu" for loong64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=loongarch64-linux-gnuf64 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-LOONG64 %s // CHECK-DEBIAN-ML-LOONG64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1391,7 +1288,6 @@ // Check linker invocation on Debian 6 MIPS 32/64-bit. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mipsel-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPSEL %s // CHECK-DEBIAN-ML-MIPSEL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1407,7 +1303,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL %s // CHECK-DEBIAN-ML-MIPS64EL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1423,7 +1318,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnu -rtlib=platform --unwindlib=platform -mabi=n32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-N32 %s // CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1439,7 +1333,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-O32 %s // CHECK-DEBIAN-ML-MIPS64EL-O32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1455,12 +1348,10 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64-unknown-linux-gnu --rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64-GNUABI %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=n64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64-GNUABI %s // CHECK-DEBIAN-ML-MIPS64-GNUABI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1477,12 +1368,10 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-GNUABI %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=n64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-GNUABI %s // CHECK-DEBIAN-ML-MIPS64EL-GNUABI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1500,7 +1389,6 @@ // Test linker invocation for Freescale SDK (OpenEmbedded). // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc-fsl-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/freescale_ppc_tree \ // RUN: | FileCheck --check-prefix=CHECK-FSL-PPC %s // CHECK-FSL-PPC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1510,7 +1398,6 @@ // CHECK-FSL-PPC: "-L[[SYSROOT]]/usr/lib" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64-fsl-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/freescale_ppc64_tree \ // RUN: | FileCheck --check-prefix=CHECK-FSL-PPC64 %s // CHECK-FSL-PPC64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1520,53 +1407,41 @@ // // Check that crtfastmath.o is linked with -ffast-math and with -Ofast. // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -funsafe-math-optimizations\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -O3\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -O3 -Ofast\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math -fno-fast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -fno-fast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -fno-unsafe-math-optimizations \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -fno-fast-math -Ofast \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -fno-unsafe-math-optimizations -Ofast \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // We don't have crtfastmath.o in the i386 tree, use it to check that file // detection works. // RUN: %clang --target=i386-unknown-linux -no-pie -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // CHECK-CRTFASTMATH: usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtfastmath.o @@ -1574,21 +1449,18 @@ // Check that we link in gcrt1.o when compiling with -pg // RUN: %clang -pg --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>& 1 \ // RUN: | FileCheck --check-prefix=CHECK-PG %s // CHECK-PG: gcrt1.o // GCC forwards -u to the linker. // RUN: %clang -u asdf --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>& 1 \ // RUN: | FileCheck --check-prefix=CHECK-u %s // CHECK-u: "-u" "asdf" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armeb-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMEB %s // CHECK-ARMEB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1598,7 +1470,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // CHECK-ARMV7EB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1609,20 +1480,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // CHECK-ARMV7EL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1633,20 +1501,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // CHECK-AARCH64BE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1657,20 +1522,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s // CHECK-AARCH64LE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1681,7 +1543,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s @@ -1775,7 +1636,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO %s // CHECK-LD-GENTOO-NOT: warning: // CHECK-LD-GENTOO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1791,7 +1651,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-32 %s // CHECK-LD-GENTOO-32-NOT: warning: // CHECK-LD-GENTOO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1807,7 +1666,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-X32 %s // CHECK-LD-GENTOO-X32-NOT: warning: // CHECK-LD-GENTOO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1833,7 +1691,6 @@ // Check whether gcc7 install works fine on Amazon Linux AMI // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-amazon-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ami_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-AMI %s // CHECK-LD-AMI-NOT: warning: @@ -1853,7 +1710,6 @@ // Check whether the OpenEmbedded ARM libs are added correctly. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-oe-linux-gnueabi -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s @@ -1872,7 +1728,6 @@ // Check whether the OpenEmbedded AArch64 libs are added correctly. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-oe-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s diff --git a/clang/test/Driver/linux-musl-header-search.cpp b/clang/test/Driver/linux-musl-header-search.cpp index c6d958583d0158..acff5b71aa65a8 100644 --- a/clang/test/Driver/linux-musl-header-search.cpp +++ b/clang/test/Driver/linux-musl-header-search.cpp @@ -2,7 +2,7 @@ // RUN: --target=x86_64-linux-musl -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-LIBCXX %s // RESOURCE_DIR/include comes after /usr/include on linux-musl. @@ -18,7 +18,7 @@ // RUN: --target=x86_64-linux-musl \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-NOBUILTININC %s // CHECK-NOBUILTININC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -28,7 +28,7 @@ // RUN: --target=x86_64-linux-musl \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-NOSTDLIBINC %s // CHECK-NOSTDLIBINC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" diff --git a/clang/test/Driver/linux-per-target-runtime-dir.c b/clang/test/Driver/linux-per-target-runtime-dir.c index 8c721d82821f6a..97e746f57eda13 100644 --- a/clang/test/Driver/linux-per-target-runtime-dir.c +++ b/clang/test/Driver/linux-per-target-runtime-dir.c @@ -3,7 +3,6 @@ // RUN: -stdlib=libc++ \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-PER-TARGET-RUNTIME %s // CHECK-PER-TARGET-RUNTIME: "-cc1" diff --git a/clang/test/Driver/mips-reduced-toolchain.cpp b/clang/test/Driver/mips-reduced-toolchain.cpp index 54d269562b3a23..4c15271f7a5f55 100644 --- a/clang/test/Driver/mips-reduced-toolchain.cpp +++ b/clang/test/Driver/mips-reduced-toolchain.cpp @@ -4,7 +4,7 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=mips-linux-gnu \ // RUN: --sysroot=%S/Inputs/debian_reduced_mips_tree \ -// RUN: --gcc-toolchain="" -no-pie \ +// RUN: -no-pie \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPS %s // CHECK-DEBIAN-MIPS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-DEBIAN-MIPS: "{{.*}}/usr/lib/gcc/mips-linux-gnu/4.7{{/|\\\\}}crtbegin.o" @@ -16,7 +16,7 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=mipsel-linux-gnu \ // RUN: --sysroot=%S/Inputs/debian_reduced_mips_tree \ -// RUN: --gcc-toolchain="" -no-pie \ +// RUN: -no-pie \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPSEL %s // CHECK-DEBIAN-MIPSEL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-DEBIAN-MIPSEL: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.7{{/|\\\\}}crtbegin.o" diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm index d0cab0cbcb31c7..dea9cf998a5401 100644 --- a/clang/test/Driver/module-output.cppm +++ b/clang/test/Driver/module-output.cppm @@ -33,6 +33,9 @@ // RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/Hello.pcm -fmodule-output -c -fsyntax-only \ // RUN: -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED +// Test that we can emit a warning if the type of the input file is not a module interface unit. +// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp + //--- Hello.cppm export module Hello; @@ -55,3 +58,8 @@ export module AnotherModule; // CHECK: "-emit-obj" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/Hello-{{.*}}.o" "-x" "pcm" "{{.*}}/Hello.pcm" // CHECK: "-emit-module-interface" {{.*}}"-main-file-name" "AnotherModule.cppm" {{.*}}"-o" "{{.*}}/AnotherModule.pcm" "-x" "c++" "{{.*}}/AnotherModule.cppm" // CHECK: "-emit-obj" {{.*}}"-main-file-name" "AnotherModule.cppm" {{.*}}"-o" "{{.*}}/AnotherModule-{{.*}}.o" "-x" "pcm" "{{.*}}/AnotherModule.pcm" + +//--- a.cpp +export module a; + +// CHECK: warning: argument unused during compilation: '-fmodule-output' diff --git a/clang/test/Driver/netbsd.cpp b/clang/test/Driver/netbsd.cpp index f63391580ad0ba..6b8a86d6ee532c 100644 --- a/clang/test/Driver/netbsd.cpp +++ b/clang/test/Driver/netbsd.cpp @@ -196,7 +196,6 @@ // RUN: --target=x86_64-unknown-netbsd \ // RUN: -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/basic_netbsd_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" diff --git a/clang/test/Driver/ohos.c b/clang/test/Driver/ohos.c index dfb7981525fd2a..b1ce61e7227b6b 100644 --- a/clang/test/Driver/ohos.c +++ b/clang/test/Driver/ohos.c @@ -230,7 +230,6 @@ // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=arm64-linux-ohos -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-OHOS-PTHREAD %s diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c index d705be44e595d8..d21db7019a1aa6 100644 --- a/clang/test/Driver/openmp-offload-gpu.c +++ b/clang/test/Driver/openmp-offload-gpu.c @@ -304,8 +304,7 @@ // RUN: | FileCheck %s --check-prefix=CHECK-EMIT-LLVM-IR-BC // CHECK-EMIT-LLVM-IR-BC: "-cc1"{{.*}}"-triple" "nvptx64-nvidia-cuda"{{.*}}"-emit-llvm-bc" -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target=nvptx64-nvida-cuda -march=sm_70 \ -// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-new-nvptx-test.bc \ +// RUN: %clang -### -fopenmp=libomp --offload-arch=sm_89 \ // RUN: -nogpulib %s -o openmp-offload-gpu 2>&1 \ // RUN: | FileCheck -check-prefix=DRIVER_EMBEDDING %s diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c index aeddead6dbf8f4..f5d07454227906 100644 --- a/clang/test/Driver/pic.c +++ b/clang/test/Driver/pic.c @@ -128,15 +128,15 @@ // Make sure -pie is passed to along to ld and that the right *crt* files // are linked in. // RUN: %clang %s -target i386-unknown-freebsd -fPIE -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform \ +// RUN: -rtlib=platform \ // RUN: --sysroot=%S/Inputs/basic_freebsd_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // RUN: %clang %s -target i386-linux-gnu -fPIE -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform --unwindlib=platform \ +// RUN: -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // RUN: %clang %s -target i386-linux-gnu -fPIC -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform --unwindlib=platform \ +// RUN: -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // @@ -149,7 +149,6 @@ // RUN: %clang -c %s -target i386-unknown-unknown -static -fPIC -### 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIC2 // RUN: %clang %s -target i386-linux-gnu -static -fPIC -### \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-STATIC // diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 052956dfa2dcea..ce4947d2bc47b4 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -41,10 +41,10 @@ // FAST-UNALIGNED-ACCESS: "-target-feature" "+fast-unaligned-access" // NO-FAST-UNALIGNED-ACCESS: "-target-feature" "-fast-unaligned-access" -// RUN: %clang --target=riscv32-unknown-elf --gcc-toolchain="" -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE -// RUN: %clang --target=riscv32-unknown-elf --gcc-toolchain="" -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE -// RUN: %clang --target=riscv64-unknown-elf --gcc-toolchain="" -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE -// RUN: %clang --target=riscv64-unknown-elf --gcc-toolchain="" -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE +// RUN: %clang --target=riscv32-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE +// RUN: %clang --target=riscv32-unknown-elf -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE +// RUN: %clang --target=riscv64-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE +// RUN: %clang --target=riscv64-unknown-elf -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE // // UWTABLE: "-funwind-tables=2" // NOUWTABLE-NOT: "-funwind-tables=2" diff --git a/clang/test/Driver/solaris-ld-sanitizer.c b/clang/test/Driver/solaris-ld-sanitizer.c index a59164787cada1..fbbd83f2d9e528 100644 --- a/clang/test/Driver/solaris-ld-sanitizer.c +++ b/clang/test/Driver/solaris-ld-sanitizer.c @@ -4,47 +4,47 @@ /// Check sparc-sun-solaris2.11, 32bit // RUN: %clang --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 32bit // RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 32bit // RUN: %clang --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 32bit // RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s // CHECK-LD-NOT: "-z" "relax=transtls" /// Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s // RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld=gld \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-GLD-X64-UBSAN %s // CHECK-LD-X64-UBSAN: "-z" "relax=transtls" @@ -56,12 +56,12 @@ /// Check i386-pc-solaris2.11, 32bit, shared libclang_rt.asan // RUN: %clang -fsanitize=address -shared-libasan --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN-SHARED %s // CHECK-LD-X32-ASAN-SHARED: "-z" "now" /// Check i386-pc-solaris2.11, 32bit, static libclang_rt.asan // RUN: %clang -fsanitize=address --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN %s // CHECK-LD-X32-ASAN-NOT: "-z" "now" diff --git a/clang/test/Driver/solaris-ld-values.c b/clang/test/Driver/solaris-ld-values.c index d7b6734f9f91ec..6f0a5b5957f014 100644 --- a/clang/test/Driver/solaris-ld-values.c +++ b/clang/test/Driver/solaris-ld-values.c @@ -5,7 +5,6 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-ANSI %s // CHECK-LD-SPARC32-ANSI: values-Xc.o @@ -13,7 +12,6 @@ // RUN: %clang -std=c89 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C89 %s // CHECK-LD-SPARC32-C89: values-Xc.o @@ -21,7 +19,6 @@ // RUN: %clang -std=c90 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C90 %s // CHECK-LD-SPARC32-C90: values-Xc.o @@ -29,7 +26,6 @@ // RUN: %clang -std=iso9899:199409 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C94 %s // CHECK-LD-SPARC32-C94: values-Xc.o @@ -37,7 +33,6 @@ // RUN: %clang -std=c11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C11 %s // CHECK-LD-SPARC32-C11: values-Xc.o @@ -45,7 +40,6 @@ // RUN: %clang -std=gnu89 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU89 %s // CHECK-LD-SPARC32-GNU89: values-Xa.o @@ -53,7 +47,6 @@ // RUN: %clang -std=gnu90 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU90 %s // CHECK-LD-SPARC32-GNU90: values-Xa.o @@ -61,7 +54,6 @@ // RUN: %clang -std=gnu11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU11 %s // CHECK-LD-SPARC32-GNU11: values-Xa.o @@ -70,7 +62,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ANSI %s // CHECK-LD-X32-ANSI: values-Xc.o diff --git a/clang/test/Driver/solaris-ld-values.cpp b/clang/test/Driver/solaris-ld-values.cpp index 4230fabffcbbc6..566252f551d513 100644 --- a/clang/test/Driver/solaris-ld-values.cpp +++ b/clang/test/Driver/solaris-ld-values.cpp @@ -5,7 +5,6 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-ANSI %s // CHECK-LD-SPARC32-ANSI: values-Xc.o @@ -13,7 +12,6 @@ // RUN: %clang -std=c++98 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-CPP98 %s // CHECK-LD-SPARC32-CPP98: values-Xc.o @@ -21,7 +19,6 @@ // RUN: %clang -std=c++11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-CPP11 %s // CHECK-LD-SPARC32-CPP11: values-Xc.o @@ -29,7 +26,6 @@ // RUN: %clang -std=gnu++98 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNUPP98 %s // CHECK-LD-SPARC32-GNUPP98: values-Xa.o @@ -38,7 +34,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -ANSI -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ANSI %s // CHECK-LD-X32-ANSI: values-Xa.o diff --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c index df4fa7b4c9ebd6..6d74389e89222c 100644 --- a/clang/test/Driver/solaris-ld.c +++ b/clang/test/Driver/solaris-ld.c @@ -3,11 +3,9 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-LD %s // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-GLD %s // CHECK-LD-SPARC32-NOT: warning: @@ -31,7 +29,6 @@ // Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 -### %s 2>&1 --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s // CHECK-LD-SPARC64-NOT: warning: @@ -53,7 +50,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -### %s 2>&1 --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s // CHECK-LD-X32-NOT: warning: @@ -76,7 +72,6 @@ // Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X64 %s // CHECK-LD-X64-NOT: warning: @@ -99,7 +94,6 @@ // Check the right -l flags are present with -shared // RUN: %clang -### %s -shared 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-SPARC32-SHARED %s // CHECK-SPARC32-SHARED: "{{.*}}ld{{(.exe)?}}" @@ -109,61 +103,51 @@ // Check that libm is only linked with clang++. // RUN: %clang -### %s --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOLIBM %s // RUN: %clang -### %s -shared --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOLIBM %s // RUN: %clangxx -### %s --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LIBM %s // RUN: %clangxx -### %s -shared --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LIBM %s // CHECK-LIBM: "-lm" // CHECK-NOLIBM-NOT: "-lm" // Check the right ld flags are present with -pie. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // Check that -shared/-r/-static disable PIE. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s @@ -184,19 +168,15 @@ // Check that crt{begin,end}S.o is linked with -shared/-pie. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTS %s // CHECK-CRTS: crtbeginS.o @@ -208,11 +188,9 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-SPARC32 %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC32 %s // CHECK-CRTFASTMATH-SPARC32: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -221,11 +199,9 @@ // Check sparc-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-SPARC64 %s // RUN: %clang -m64 --target=sparc-sun-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC64 %s // CHECK-CRTFASTMATH-SPARC64: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -234,11 +210,9 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang --target=i386-pc-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-X32 %s // RUN: %clang --target=i386-pc-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-X32 %s // CHECK-CRTFASTMATH-X32: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -247,11 +221,9 @@ // Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=i386-pc-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-X64 %s // RUN: %clang -m64 --target=i386-pc-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-X64 %s // CHECK-CRTFASTMATH-X64: "-isysroot" "[[SYSROOT:[^"]+]]" diff --git a/clang/test/ExtractAPI/anonymous_record_no_typedef.c b/clang/test/ExtractAPI/anonymous_record_no_typedef.c index 0e50f4a0948c94..049e8b1f85bb96 100644 --- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c +++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c @@ -1,8 +1,9 @@ +// XFAIL: * // RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c index 3c1ef5c45b634d..12ac73f0d4295a 100644 --- a/clang/test/ExtractAPI/availability.c +++ b/clang/test/ExtractAPI/availability.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ diff --git a/clang/test/ExtractAPI/bool.c b/clang/test/ExtractAPI/bool.c index f4082edeb02ede..efab6dfeef03b2 100644 --- a/clang/test/ExtractAPI/bool.c +++ b/clang/test/ExtractAPI/bool.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \ // RUN: %t/input.h -o %t/output.json // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/bool.cpp b/clang/test/ExtractAPI/bool.cpp index 1b445e220a4a0e..f7d10c61dba4b7 100644 --- a/clang/test/ExtractAPI/bool.cpp +++ b/clang/test/ExtractAPI/bool.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/class.cpp b/clang/test/ExtractAPI/class.cpp index 21cac43057524a..0c5db8e9c9d215 100644 --- a/clang/test/ExtractAPI/class.cpp +++ b/clang/test/ExtractAPI/class.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp index b04dca6bffda16..4f2670d7b69977 100644 --- a/clang/test/ExtractAPI/class_template.cpp +++ b/clang/test/ExtractAPI/class_template.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp index 0d38fd1b7f5306..3d7b09f93ed6de 100644 --- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp +++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp index eba069319ce450..c8d9cc78d41c5c 100644 --- a/clang/test/ExtractAPI/class_template_partial_spec.cpp +++ b/clang/test/ExtractAPI/class_template_partial_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. @@ -15,7 +15,7 @@ template class Foo {}; template class Foo {}; -/// expected-no-diagnostics +// expected-no-diagnostics //--- reference.output.json.in { diff --git a/clang/test/ExtractAPI/class_template_spec.cpp b/clang/test/ExtractAPI/class_template_spec.cpp index 4b183cbb844580..06a95314dc4aa0 100644 --- a/clang/test/ExtractAPI/class_template_spec.cpp +++ b/clang/test/ExtractAPI/class_template_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp index ff4e71026e7283..443eac2971f0e5 100644 --- a/clang/test/ExtractAPI/concept.cpp +++ b/clang/test/ExtractAPI/concept.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -std=c++20 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/constructor_destructor.cpp b/clang/test/ExtractAPI/constructor_destructor.cpp index 9742d4bae26133..27112c95ac45c2 100644 --- a/clang/test/ExtractAPI/constructor_destructor.cpp +++ b/clang/test/ExtractAPI/constructor_destructor.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. @@ -137,7 +137,7 @@ class Foo { "precise": "c:@S@Foo@F@Foo#" }, "kind": { - "displayName": "Instance Method", + "displayName": "Constructor", "identifier": "c++.method" }, "location": { @@ -193,7 +193,7 @@ class Foo { "precise": "c:@S@Foo@F@~Foo#" }, "kind": { - "displayName": "Instance Method", + "displayName": "Destructor", "identifier": "c++.method" }, "location": { diff --git a/clang/test/ExtractAPI/conversions.cpp b/clang/test/ExtractAPI/conversions.cpp index fc8d0675443730..07688ff770979e 100644 --- a/clang/test/ExtractAPI/conversions.cpp +++ b/clang/test/ExtractAPI/conversions.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c index e6b72d5881e7d1..e668f69bc7e05f 100644 --- a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c +++ b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c @@ -5,18 +5,19 @@ // RUN: %t/reference.main.json.in >> %t/reference.main.json // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.test.json.in >> %t/reference.test.json -// RUN: %clang_cc1 %t/test.c %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0 +// RUN: %clang_cc1 %t/test.c %t/main.c -emit-symbol-graph --pretty-sgf \ +// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0 // Test main.json // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/SymbolGraphs/main.json > %t/output-normalized.json +// RUN: %t/SymbolGraphs/main.c.symbols.json > %t/output-normalized.json // RUN: diff %t/reference.main.json %t/output-normalized.json // Test test.json // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/SymbolGraphs/test.json > %t/output-normalized.json +// RUN: %t/SymbolGraphs/test.c.symbols.json > %t/output-normalized.json // RUN: diff %t/reference.test.json %t/output-normalized.json // CHECK-NOT: error: diff --git a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c index 8599e82e10783a..b00b5f5237c9a3 100644 --- a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c +++ b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c @@ -3,11 +3,12 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0 +// RUN: %clang_cc1 %t/main.c -emit-symbol-graph --pretty-sgf \ +// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0 // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/SymbolGraphs/main.json >> %t/output-normalized.json +// RUN: %t/SymbolGraphs/main.c.symbols.json >> %t/output-normalized.json // RUN: diff %t/reference.output.json %t/output-normalized.json // CHECK-NOT: error: diff --git a/clang/test/ExtractAPI/enum.c b/clang/test/ExtractAPI/enum.c index 94499d9fc3a639..1cdf45ca3cdf4b 100644 --- a/clang/test/ExtractAPI/enum.c +++ b/clang/test/ExtractAPI/enum.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp index f05e826a8eb491..2058ed008cfe40 100644 --- a/clang/test/ExtractAPI/field_template.cpp +++ b/clang/test/ExtractAPI/field_template.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/function_noexcepts.cpp b/clang/test/ExtractAPI/function_noexcepts.cpp index 3fc7263cd6a186..d95eaaa7e769a5 100644 --- a/clang/test/ExtractAPI/function_noexcepts.cpp +++ b/clang/test/ExtractAPI/function_noexcepts.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp index 8def9745bcce8e..f43a618ec0c366 100644 --- a/clang/test/ExtractAPI/global_func_template.cpp +++ b/clang/test/ExtractAPI/global_func_template.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp index a24263dc14584f..fe046e9c3b9dac 100644 --- a/clang/test/ExtractAPI/global_func_template_spec.cpp +++ b/clang/test/ExtractAPI/global_func_template_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_record.c b/clang/test/ExtractAPI/global_record.c index 623032b45bfd2c..a08d51d21f9556 100644 --- a/clang/test/ExtractAPI/global_record.c +++ b/clang/test/ExtractAPI/global_record.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \ // RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_record_multifile.c b/clang/test/ExtractAPI/global_record_multifile.c index f9d3889b5d9de3..ffdfbcb7eb8087 100644 --- a/clang/test/ExtractAPI/global_record_multifile.c +++ b/clang/test/ExtractAPI/global_record_multifile.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \ // RUN: %t/input1.h %t/input2.h %t/input3.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_var_template.cpp b/clang/test/ExtractAPI/global_var_template.cpp index bee2ea601bd72b..94f3713cd3d31b 100644 --- a/clang/test/ExtractAPI/global_var_template.cpp +++ b/clang/test/ExtractAPI/global_var_template.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp index e98076cdb1d016..91084f258878ee 100644 --- a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp +++ b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp index cca2ab3db7b8bd..ff4d8d17aecbe9 100644 --- a/clang/test/ExtractAPI/global_var_template_spec.cpp +++ b/clang/test/ExtractAPI/global_var_template_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/known_files_only.c b/clang/test/ExtractAPI/known_files_only.c index 68881aa9e3aadb..de1e786c1969dd 100644 --- a/clang/test/ExtractAPI/known_files_only.c +++ b/clang/test/ExtractAPI/known_files_only.c @@ -1,17 +1,7 @@ // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \ -// RUN: %t/input1.h -o %t/output.json | FileCheck -allow-empty %s - -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: +// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=GlobalRecord -triple arm64-apple-macosx \ +// RUN: %t/input1.h -verify -o - | FileCheck %s //--- input1.h int num; @@ -24,87 +14,6 @@ char not_emitted; void foo(int); struct Foo { int a; }; -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "GlobalRecord", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "num" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@num" - }, - "kind": { - "displayName": "Global Variable", - "identifier": "c.var" - }, - "location": { - "position": { - "character": 4, - "line": 0 - }, - "uri": "file://INPUT_DIR/input1.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "num" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "num" - } - ], - "title": "num" - }, - "pathComponents": [ - "num" - ] - } - ] -} +// CHECK-NOT: input2.h + +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c index fe98626c84613e..90832fd8a2aff9 100644 --- a/clang/test/ExtractAPI/language.c +++ b/clang/test/ExtractAPI/language.c @@ -7,11 +7,11 @@ // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json -// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -x c-header -triple arm64-apple-macosx \ // RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s -// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c-header -triple arm64-apple-macosx \ // RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s -// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c++-header -triple arm64-apple-macosx \ // RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/macro_undefined.c b/clang/test/ExtractAPI/macro_undefined.c index 1a4ed20545e0d6..ec60f95d3d6c4f 100644 --- a/clang/test/ExtractAPI/macro_undefined.c +++ b/clang/test/ExtractAPI/macro_undefined.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \ // RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/macros.c b/clang/test/ExtractAPI/macros.c index d5807f6377ff63..10003fe6f6e40f 100644 --- a/clang/test/ExtractAPI/macros.c +++ b/clang/test/ExtractAPI/macros.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \ // RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/metadata_and_module.c b/clang/test/ExtractAPI/metadata_and_module.c new file mode 100644 index 00000000000000..79574a20ed95a9 --- /dev/null +++ b/clang/test/ExtractAPI/metadata_and_module.c @@ -0,0 +1,32 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=module -triple arm64-apple-macosx -x c-header %s -o %t/module.symbols.json -verify + +// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix METADATA +// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix MOD + +// expected-no-diagnostics + +// METADATA: "metadata": { +// METADATA-NEXT: "formatVersion": { +// METADATA-NEXT: "major": +// METADATA-NEXT: "minor": +// METADATA-NEXT: "patch": +// METADATA-NEXT: }, +// METADATA-NEXT: "generator": +// METADATA-NEXT: } + +// MOD: "module": { +// MOD-NEXT: "name": "module", +// MOD-NEXT: "platform": { +// MOD-NEXT: "architecture": "arm64", +// MOD-NEXT: "operatingSystem": { +// MOD-NEXT: "minimumVersion": { +// MOD-NEXT: "major": +// MOD-NEXT: "minor": +// MOD-NEXT: "patch": +// MOD-NEXT: }, +// MOD-NEXT: "name": "macosx" +// MOD-NEXT: }, +// MOD-NEXT: "vendor": "apple" +// MOD-NEXT: } +// MOD-NEXT: } diff --git a/clang/test/ExtractAPI/method_template.cpp b/clang/test/ExtractAPI/method_template.cpp index 8d832337216a28..714f9cac26c208 100644 --- a/clang/test/ExtractAPI/method_template.cpp +++ b/clang/test/ExtractAPI/method_template.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp index 706d99da558fe2..8eaffdefd827a9 100644 --- a/clang/test/ExtractAPI/method_template_spec.cpp +++ b/clang/test/ExtractAPI/method_template_spec.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/methods.cpp b/clang/test/ExtractAPI/methods.cpp index 8b024a8c3036f1..412c0bb3f903c3 100644 --- a/clang/test/ExtractAPI/methods.cpp +++ b/clang/test/ExtractAPI/methods.cpp @@ -1,467 +1,221 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ -// RUN: -x c++-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x c++-header %s -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -//--- input.h class Foo { + // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETCOUNT int getCount(); + // GETCOUNT: "!testRelLabel": "memberOf $ c:@S@Foo@F@getCount# $ c:@S@Foo" + // GETCOUNT-LABEL: "!testLabel": "c:@S@Foo@F@getCount#" + // GETCOUNT: "accessLevel": "private", + // GETCOUNT: "declarationFragments": [ + // GETCOUNT-NEXT: { + // GETCOUNT-NEXT: "kind": "typeIdentifier", + // GETCOUNT-NEXT: "preciseIdentifier": "c:I", + // GETCOUNT-NEXT: "spelling": "int" + // GETCOUNT-NEXT: }, + // GETCOUNT-NEXT: { + // GETCOUNT-NEXT: "kind": "text", + // GETCOUNT-NEXT: "spelling": " " + // GETCOUNT-NEXT: }, + // GETCOUNT-NEXT: { + // GETCOUNT-NEXT: "kind": "identifier", + // GETCOUNT-NEXT: "spelling": "getCount" + // GETCOUNT-NEXT: }, + // GETCOUNT-NEXT: { + // GETCOUNT-NEXT: "kind": "text", + // GETCOUNT-NEXT: "spelling": "();" + // GETCOUNT-NEXT: } + // GETCOUNT-NEXT: ], + // GETCOUNT: "functionSignature": { + // GETCOUNT-NEXT: "returns": [ + // GETCOUNT-NEXT: { + // GETCOUNT-NEXT: "kind": "typeIdentifier", + // GETCOUNT-NEXT: "preciseIdentifier": "c:I", + // GETCOUNT-NEXT: "spelling": "int" + // GETCOUNT-NEXT: } + // GETCOUNT-NEXT: ] + // GETCOUNT-NEXT: }, + // GETCOUNT: "displayName": "Instance Method", + // GETCOUNT-NEXT: "identifier": "c++.method" + // GETCOUNT: "title": "getCount" + // GETCOUNT: "pathComponents": [ + // GETCOUNT-NEXT: "Foo", + // GETCOUNT-NEXT: "getCount" + // GETCOUNT-NEXT: ] + // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SETL void setLength(int length) noexcept; + // SETL: "!testRelLabel": "memberOf $ c:@S@Foo@F@setLength#I# $ c:@S@Foo" + // SETL-LABEL: "!testLabel": "c:@S@Foo@F@setLength#I#" + // SETL: "declarationFragments": [ + // SETL-NEXT: { + // SETL-NEXT: "kind": "typeIdentifier", + // SETL-NEXT: "preciseIdentifier": "c:v", + // SETL-NEXT: "spelling": "void" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": " " + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "identifier", + // SETL-NEXT: "spelling": "setLength" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": "(" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "typeIdentifier", + // SETL-NEXT: "preciseIdentifier": "c:I", + // SETL-NEXT: "spelling": "int" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": " " + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "internalParam", + // SETL-NEXT: "spelling": "length" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": ")" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": " " + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "keyword", + // SETL-NEXT: "spelling": "noexcept" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": ";" + // SETL-NEXT: } + // SETL-NEXT: ], + // SETL: "functionSignature": { + // SETL-NEXT: "parameters": [ + // SETL-NEXT: { + // SETL-NEXT: "declarationFragments": [ + // SETL-NEXT: { + // SETL-NEXT: "kind": "typeIdentifier", + // SETL-NEXT: "preciseIdentifier": "c:I", + // SETL-NEXT: "spelling": "int" + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "text", + // SETL-NEXT: "spelling": " " + // SETL-NEXT: }, + // SETL-NEXT: { + // SETL-NEXT: "kind": "internalParam", + // SETL-NEXT: "spelling": "length" + // SETL-NEXT: } + // SETL-NEXT: ], + // SETL-NEXT: "name": "length" + // SETL-NEXT: } + // SETL-NEXT: ], + // SETL-NEXT: "returns": [ + // SETL-NEXT: { + // SETL-NEXT: "kind": "typeIdentifier", + // SETL-NEXT: "preciseIdentifier": "c:v", + // SETL-NEXT: "spelling": "void" + // SETL-NEXT: } + // SETL-NEXT: ] + // SETL-NEXT: }, public: + // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETFOO static double getFoo(); + // GETFOO: "!testRelLabel": "memberOf $ c:@S@Foo@F@getFoo#S $ c:@S@Foo" + + // GETFOO-LABEL: "!testLabel": "c:@S@Foo@F@getFoo#S" + // GETFOO: "accessLevel": "public", + // GETFOO: "declarationFragments": [ + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "keyword", + // GETFOO-NEXT: "spelling": "static" + // GETFOO-NEXT: }, + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "text", + // GETFOO-NEXT: "spelling": " " + // GETFOO-NEXT: }, + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "typeIdentifier", + // GETFOO-NEXT: "preciseIdentifier": "c:d", + // GETFOO-NEXT: "spelling": "double" + // GETFOO-NEXT: }, + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "text", + // GETFOO-NEXT: "spelling": " " + // GETFOO-NEXT: }, + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "identifier", + // GETFOO-NEXT: "spelling": "getFoo" + // GETFOO-NEXT: }, + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "text", + // GETFOO-NEXT: "spelling": "();" + // GETFOO-NEXT: } + // GETFOO-NEXT: ], + // GETFOO: "functionSignature": { + // GETFOO-NEXT: "returns": [ + // GETFOO-NEXT: { + // GETFOO-NEXT: "kind": "typeIdentifier", + // GETFOO-NEXT: "preciseIdentifier": "c:d", + // GETFOO-NEXT: "spelling": "double" + // GETFOO-NEXT: } + // GETFOO-NEXT: ] + // GETFOO-NEXT: }, + // GETFOO: "kind": { + // GETFOO-NEXT: "displayName": "Static Method", + // GETFOO-NEXT: "identifier": "c++.type.method" + // GETFOO-NEXT: }, protected: + // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETBAR constexpr int getBar() const; + // GETBAR: "!testRelLabel": "memberOf $ c:@S@Foo@F@getBar#1 $ c:@S@Foo" + + // GETBAR-LABEL: "!testLabel": "c:@S@Foo@F@getBar#1" + // GETBAR: "accessLevel": "protected" + // GETBAR: "declarationFragments": [ + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "keyword", + // GETBAR-NEXT: "spelling": "constexpr" + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "text", + // GETBAR-NEXT: "spelling": " " + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "typeIdentifier", + // GETBAR-NEXT: "preciseIdentifier": "c:I", + // GETBAR-NEXT: "spelling": "int" + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "text", + // GETBAR-NEXT: "spelling": " " + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "identifier", + // GETBAR-NEXT: "spelling": "getBar" + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "text", + // GETBAR-NEXT: "spelling": "() " + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "keyword", + // GETBAR-NEXT: "spelling": "const" + // GETBAR-NEXT: }, + // GETBAR-NEXT: { + // GETBAR-NEXT: "kind": "text", + // GETBAR-NEXT: "spelling": ";" + // GETBAR-NEXT: } + // GETBAR-NEXT: ], }; -/// expected-no-diagnostics -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:@S@Foo@F@getCount#", - "target": "c:@S@Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:@S@Foo@F@setLength#I#", - "target": "c:@S@Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:@S@Foo@F@getBar#1", - "target": "c:@S@Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:@S@Foo@F@getFoo#S", - "target": "c:@S@Foo", - "targetFallback": "Foo" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "class" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Foo" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c++", - "precise": "c:@S@Foo" - }, - "kind": { - "displayName": "Class", - "identifier": "c++.class" - }, - "location": { - "position": { - "character": 6, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "title": "Foo" - }, - "pathComponents": [ - "Foo" - ] - }, - { - "accessLevel": "private", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "getCount" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - } - ] - }, - "identifier": { - "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@getCount#" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "c++.method" - }, - "location": { - "position": { - "character": 6, - "line": 1 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "getCount" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "getCount" - } - ], - "title": "getCount" - }, - "pathComponents": [ - "Foo", - "getCount" - ] - }, - { - "accessLevel": "private", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "setLength" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "length" - }, - { - "kind": "text", - "spelling": ")" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "noexcept" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "length" - } - ], - "name": "length" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@setLength#I#" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "c++.method" - }, - "location": { - "position": { - "character": 7, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "setLength" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "setLength" - } - ], - "title": "setLength" - }, - "pathComponents": [ - "Foo", - "setLength" - ] - }, - { - "accessLevel": "protected", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "constexpr" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "getBar" - }, - { - "kind": "text", - "spelling": "() " - }, - { - "kind": "keyword", - "spelling": "const" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - } - ] - }, - "identifier": { - "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@getBar#1" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "c++.method" - }, - "location": { - "position": { - "character": 16, - "line": 9 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "getBar" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "getBar" - } - ], - "title": "getBar" - }, - "pathComponents": [ - "Foo", - "getBar" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "static" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:d", - "spelling": "double" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "getFoo" - }, - { - "kind": "text", - "spelling": "();" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:d", - "spelling": "double" - } - ] - }, - "identifier": { - "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@getFoo#S" - }, - "kind": { - "displayName": "Static Method", - "identifier": "c++.type.method" - }, - "location": { - "position": { - "character": 16, - "line": 6 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "getFoo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "getFoo" - } - ], - "title": "getFoo" - }, - "pathComponents": [ - "Foo", - "getFoo" - ] - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/multiple_inheritance.cpp b/clang/test/ExtractAPI/multiple_inheritance.cpp index a1f069be0de617..7d49cf4326465e 100644 --- a/clang/test/ExtractAPI/multiple_inheritance.cpp +++ b/clang/test/ExtractAPI/multiple_inheritance.cpp @@ -3,7 +3,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/namespace.cpp b/clang/test/ExtractAPI/namespace.cpp index e0c36dd3d60fed..73e0728b9a4416 100644 --- a/clang/test/ExtractAPI/namespace.cpp +++ b/clang/test/ExtractAPI/namespace.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/nested_namespaces.cpp b/clang/test/ExtractAPI/nested_namespaces.cpp index bd13ef93807c01..c6912cfb46312f 100644 --- a/clang/test/ExtractAPI/nested_namespaces.cpp +++ b/clang/test/ExtractAPI/nested_namespaces.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/objc_block.m b/clang/test/ExtractAPI/objc_block.m index a7a4f5696333c1..4a4335ec09832d 100644 --- a/clang/test/ExtractAPI/objc_block.m +++ b/clang/test/ExtractAPI/objc_block.m @@ -1,965 +1,630 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -fblocks -triple arm64-apple-macosx \ -// RUN: -x objective-c-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -fblocks -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -//--- input.h @interface Foo +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NOPARAM -(void)methodBlockNoParam:(void (^)())block; +// NOPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockNoParam:" +// NOPARAM: "declarationFragments": [ +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": "- (" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "typeIdentifier", +// NOPARAM-NEXT: "preciseIdentifier": "c:v", +// NOPARAM-NEXT: "spelling": "void" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": ") " +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "identifier", +// NOPARAM-NEXT: "spelling": "methodBlockNoParam:" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": "(" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "typeIdentifier", +// NOPARAM-NEXT: "preciseIdentifier": "c:v", +// NOPARAM-NEXT: "spelling": "void" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": " (^" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": ")()) " +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "internalParam", +// NOPARAM-NEXT: "spelling": "block" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": ";" +// NOPARAM-NEXT: } +// NOPARAM-NEXT: ], +// NOPARAM: "functionSignature": { +// NOPARAM-NEXT: "parameters": [ +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "declarationFragments": [ +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": "(" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "typeIdentifier", +// NOPARAM-NEXT: "preciseIdentifier": "c:v", +// NOPARAM-NEXT: "spelling": "void" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": " (^" +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "text", +// NOPARAM-NEXT: "spelling": ")()) " +// NOPARAM-NEXT: }, +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "internalParam", +// NOPARAM-NEXT: "spelling": "block" +// NOPARAM-NEXT: } +// NOPARAM-NEXT: ], +// NOPARAM-NEXT: "name": "block" +// NOPARAM-NEXT: } +// NOPARAM-NEXT: ], +// NOPARAM-NEXT: "returns": [ +// NOPARAM-NEXT: { +// NOPARAM-NEXT: "kind": "typeIdentifier", +// NOPARAM-NEXT: "preciseIdentifier": "c:v", +// NOPARAM-NEXT: "spelling": "void" +// NOPARAM-NEXT: } +// NOPARAM-NEXT: ] +// NOPARAM-NEXT: } + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PARAM -(void)methodBlockWithParam:(int (^)(int foo))block; +// PARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithParam:" +// PARAM: "declarationFragments": [ +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": "- (" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:v", +// PARAM-NEXT: "spelling": "void" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ") " +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "identifier", +// PARAM-NEXT: "spelling": "methodBlockWithParam:" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": "(" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:I", +// PARAM-NEXT: "spelling": "int" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": " (^" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ")(" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:I", +// PARAM-NEXT: "spelling": "int" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": " " +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "internalParam", +// PARAM-NEXT: "spelling": "foo" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ")) " +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "internalParam", +// PARAM-NEXT: "spelling": "block" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ";" +// PARAM-NEXT: } +// PARAM-NEXT: ], +// PARAM: "functionSignature": { +// PARAM-NEXT: "parameters": [ +// PARAM-NEXT: { +// PARAM-NEXT: "declarationFragments": [ +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": "(" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:I", +// PARAM-NEXT: "spelling": "int" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": " (^" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ")(" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:I", +// PARAM-NEXT: "spelling": "int" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": " " +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "internalParam", +// PARAM-NEXT: "spelling": "foo" +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "text", +// PARAM-NEXT: "spelling": ")) " +// PARAM-NEXT: }, +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "internalParam", +// PARAM-NEXT: "spelling": "block" +// PARAM-NEXT: } +// PARAM-NEXT: ], +// PARAM-NEXT: "name": "block" +// PARAM-NEXT: } +// PARAM-NEXT: ], +// PARAM-NEXT: "returns": [ +// PARAM-NEXT: { +// PARAM-NEXT: "kind": "typeIdentifier", +// PARAM-NEXT: "preciseIdentifier": "c:v", +// PARAM-NEXT: "spelling": "void" +// PARAM-NEXT: } +// PARAM-NEXT: ] +// PARAM-NEXT: } + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MULTIPARAM -(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block; +// MULTIPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:" +// MULTIPARAM: "declarationFragments": [ +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": "- (" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:v", +// MULTIPARAM-NEXT: "spelling": "void" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ") " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "identifier", +// MULTIPARAM-NEXT: "spelling": "methodBlockWithMultipleParam:" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": "(" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:I", +// MULTIPARAM-NEXT: "spelling": "int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " (^" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ")(" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:I", +// MULTIPARAM-NEXT: "spelling": "int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "foo" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ", " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:i", +// MULTIPARAM-NEXT: "spelling": "unsigned int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "baz" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ")) " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "block" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ";" +// MULTIPARAM-NEXT: } +// MULTIPARAM-NEXT: ], +// MULTIPARAM: "functionSignature": { +// MULTIPARAM-NEXT: "parameters": [ +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "declarationFragments": [ +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": "(" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:I", +// MULTIPARAM-NEXT: "spelling": "int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " (^" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ")(" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:I", +// MULTIPARAM-NEXT: "spelling": "int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "foo" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ", " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:i", +// MULTIPARAM-NEXT: "spelling": "unsigned int" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": " " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "baz" +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "text", +// MULTIPARAM-NEXT: "spelling": ")) " +// MULTIPARAM-NEXT: }, +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "internalParam", +// MULTIPARAM-NEXT: "spelling": "block" +// MULTIPARAM-NEXT: } +// MULTIPARAM-NEXT: ], +// MULTIPARAM-NEXT: "name": "block" +// MULTIPARAM-NEXT: } +// MULTIPARAM-NEXT: ], +// MULTIPARAM-NEXT: "returns": [ +// MULTIPARAM-NEXT: { +// MULTIPARAM-NEXT: "kind": "typeIdentifier", +// MULTIPARAM-NEXT: "preciseIdentifier": "c:v", +// MULTIPARAM-NEXT: "spelling": "void" +// MULTIPARAM-NEXT: } +// MULTIPARAM-NEXT: ] +// MULTIPARAM-NEXT: }, + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VARIADIC -(void)methodBlockVariadic:(int (^)(int foo, ...))block; +// VARIADIC-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockVariadic:" +// VARIADIC: "declarationFragments": [ +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": "- (" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:v", +// VARIADIC-NEXT: "spelling": "void" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ") " +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "identifier", +// VARIADIC-NEXT: "spelling": "methodBlockVariadic:" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": "(" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:I", +// VARIADIC-NEXT: "spelling": "int" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": " (^" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ")(" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:I", +// VARIADIC-NEXT: "spelling": "int" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": " " +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "internalParam", +// VARIADIC-NEXT: "spelling": "foo" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ", ...)) " +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "internalParam", +// VARIADIC-NEXT: "spelling": "block" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ";" +// VARIADIC-NEXT: } +// VARIADIC-NEXT: ], +// VARIADIC: "functionSignature": { +// VARIADIC-NEXT: "parameters": [ +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "declarationFragments": [ +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": "(" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:I", +// VARIADIC-NEXT: "spelling": "int" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": " (^" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ")(" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:I", +// VARIADIC-NEXT: "spelling": "int" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": " " +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "internalParam", +// VARIADIC-NEXT: "spelling": "foo" +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "text", +// VARIADIC-NEXT: "spelling": ", ...)) " +// VARIADIC-NEXT: }, +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "internalParam", +// VARIADIC-NEXT: "spelling": "block" +// VARIADIC-NEXT: } +// VARIADIC-NEXT: ], +// VARIADIC-NEXT: "name": "block" +// VARIADIC-NEXT: } +// VARIADIC-NEXT: ], +// VARIADIC-NEXT: "returns": [ +// VARIADIC-NEXT: { +// VARIADIC-NEXT: "kind": "typeIdentifier", +// VARIADIC-NEXT: "preciseIdentifier": "c:v", +// VARIADIC-NEXT: "spelling": "void" +// VARIADIC-NEXT: } +// VARIADIC-NEXT: ] +// VARIADIC-NEXT: }, @end +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FUNC void func(int (^arg)(int foo)); +// FUNC-LABEL: "!testLabel": "c:@F@func" +// FUNC: "declarationFragments": [ +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:v", +// FUNC-NEXT: "spelling": "void" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": " " +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "identifier", +// FUNC-NEXT: "spelling": "func" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": "(" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:I", +// FUNC-NEXT: "spelling": "int" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": " (^" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "internalParam", +// FUNC-NEXT: "spelling": "arg" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": ")(" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:I", +// FUNC-NEXT: "spelling": "int" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": " " +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "internalParam", +// FUNC-NEXT: "spelling": "foo" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": "));" +// FUNC-NEXT: } +// FUNC-NEXT: ], +// FUNC: "functionSignature": { +// FUNC-NEXT: "parameters": [ +// FUNC-NEXT: { +// FUNC-NEXT: "declarationFragments": [ +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:I", +// FUNC-NEXT: "spelling": "int" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": " (^" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "internalParam", +// FUNC-NEXT: "spelling": "arg" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": ")(" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:I", +// FUNC-NEXT: "spelling": "int" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": " " +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "internalParam", +// FUNC-NEXT: "spelling": "foo" +// FUNC-NEXT: }, +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "text", +// FUNC-NEXT: "spelling": ")" +// FUNC-NEXT: } +// FUNC-NEXT: ], +// FUNC-NEXT: "name": "arg" +// FUNC-NEXT: } +// FUNC-NEXT: ], +// FUNC-NEXT: "returns": [ +// FUNC-NEXT: { +// FUNC-NEXT: "kind": "typeIdentifier", +// FUNC-NEXT: "preciseIdentifier": "c:v", +// FUNC-NEXT: "spelling": "void" +// FUNC-NEXT: } +// FUNC-NEXT: ] +// FUNC-NEXT: }, +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBAL int (^global)(int foo); +// GLOBAL-LABEL: "!testLabel": "c:@global" +// GLOBAL: "declarationFragments": [ +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "typeIdentifier", +// GLOBAL-NEXT: "preciseIdentifier": "c:I", +// GLOBAL-NEXT: "spelling": "int" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "text", +// GLOBAL-NEXT: "spelling": " (^" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "identifier", +// GLOBAL-NEXT: "spelling": "global" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "text", +// GLOBAL-NEXT: "spelling": ")(" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "typeIdentifier", +// GLOBAL-NEXT: "preciseIdentifier": "c:I", +// GLOBAL-NEXT: "spelling": "int" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "text", +// GLOBAL-NEXT: "spelling": " " +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "internalParam", +// GLOBAL-NEXT: "spelling": "foo" +// GLOBAL-NEXT: }, +// GLOBAL-NEXT: { +// GLOBAL-NEXT: "kind": "text", +// GLOBAL-NEXT: "spelling": ");" +// GLOBAL-NEXT: } +// GLOBAL-NEXT: ], ///expected-no-diagnostics - -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)Foo(im)methodBlockNoParam:", - "target": "c:objc(cs)Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Foo(im)methodBlockWithParam:", - "target": "c:objc(cs)Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:", - "target": "c:objc(cs)Foo", - "targetFallback": "Foo" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Foo(im)methodBlockVariadic:", - "target": "c:objc(cs)Foo", - "targetFallback": "Foo" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "identifier", - "spelling": "global" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ");" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:@global" - }, - "kind": { - "displayName": "Global Variable", - "identifier": "objective-c.var" - }, - "location": { - "position": { - "character": 6, - "line": 9 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "global" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "global" - } - ], - "title": "global" - }, - "pathComponents": [ - "global" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "func" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "internalParam", - "spelling": "arg" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": "));" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "internalParam", - "spelling": "arg" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ")" - } - ], - "name": "arg" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:@F@func" - }, - "kind": { - "displayName": "Function", - "identifier": "objective-c.func" - }, - "location": { - "position": { - "character": 5, - "line": 7 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "func" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "func" - } - ], - "title": "func" - }, - "pathComponents": [ - "func" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Foo" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "title": "Foo" - }, - "pathComponents": [ - "Foo" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "methodBlockNoParam:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")()) " - }, - { - "kind": "internalParam", - "spelling": "block" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")()) " - }, - { - "kind": "internalParam", - "spelling": "block" - } - ], - "name": "block" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Foo(im)methodBlockNoParam:" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 1 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "methodBlockNoParam:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "methodBlockNoParam:" - } - ], - "title": "methodBlockNoParam:" - }, - "pathComponents": [ - "Foo", - "methodBlockNoParam:" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "methodBlockWithParam:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ")) " - }, - { - "kind": "internalParam", - "spelling": "block" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ")) " - }, - { - "kind": "internalParam", - "spelling": "block" - } - ], - "name": "block" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Foo(im)methodBlockWithParam:" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "methodBlockWithParam:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "methodBlockWithParam:" - } - ], - "title": "methodBlockWithParam:" - }, - "pathComponents": [ - "Foo", - "methodBlockWithParam:" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "methodBlockWithMultipleParam:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ", " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "baz" - }, - { - "kind": "text", - "spelling": ")) " - }, - { - "kind": "internalParam", - "spelling": "block" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ", " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "baz" - }, - { - "kind": "text", - "spelling": ")) " - }, - { - "kind": "internalParam", - "spelling": "block" - } - ], - "name": "block" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "methodBlockWithMultipleParam:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "methodBlockWithMultipleParam:" - } - ], - "title": "methodBlockWithMultipleParam:" - }, - "pathComponents": [ - "Foo", - "methodBlockWithMultipleParam:" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "methodBlockVariadic:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ", ...)) " - }, - { - "kind": "internalParam", - "spelling": "block" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " (^" - }, - { - "kind": "text", - "spelling": ")(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": ", ...)) " - }, - { - "kind": "internalParam", - "spelling": "block" - } - ], - "name": "block" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Foo(im)methodBlockVariadic:" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "methodBlockVariadic:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "methodBlockVariadic:" - } - ], - "title": "methodBlockVariadic:" - }, - "pathComponents": [ - "Foo", - "methodBlockVariadic:" - ] - } - ] -} diff --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_category.m index 34b0a9e31f553c..9177d40b82644a 100644 --- a/clang/test/ExtractAPI/objc_category.m +++ b/clang/test/ExtractAPI/objc_category.m @@ -1,341 +1,21 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h -@protocol Protocol; +@protocol Protocol +@end @interface Interface @end @interface Interface (Category) +// CHECK-DAG: "!testRelLabel": "conformsTo $ c:objc(cs)Interface $ c:objc(pl)Protocol" @property int Property; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)Property $ c:objc(cs)Interface" - (void)InstanceMethod; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(im)InstanceMethod $ c:objc(cs)Interface" + (void)ClassMethod; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cm)ClassMethod $ c:objc(cs)Interface" @end -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(im)InstanceMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(cm)ClassMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(py)Property", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "conformsTo", - "source": "c:objc(cs)Interface", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "title": "Interface" - }, - "pathComponents": [ - "Interface" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "InstanceMethod" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(im)InstanceMethod" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 7 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "InstanceMethod" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "InstanceMethod" - } - ], - "title": "InstanceMethod" - }, - "pathComponents": [ - "Interface", - "InstanceMethod" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "+ (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "ClassMethod" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(cm)ClassMethod" - }, - "kind": { - "displayName": "Type Method", - "identifier": "objective-c.type.method" - }, - "location": { - "position": { - "character": 0, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "ClassMethod" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "+ " - }, - { - "kind": "identifier", - "spelling": "ClassMethod" - } - ], - "title": "ClassMethod" - }, - "pathComponents": [ - "Interface", - "ClassMethod" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Property" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(py)Property" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 14, - "line": 6 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Property" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Property" - } - ], - "title": "Property" - }, - "pathComponents": [ - "Interface", - "Property" - ] - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m new file mode 100644 index 00000000000000..47e699cb91c0e4 --- /dev/null +++ b/clang/test/ExtractAPI/objc_external_category.m @@ -0,0 +1,49 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \ +// RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify + +//--- input.h +#include "ExternalModule.h" + +@interface ExtInterface (Category) +@property int Property; +- (void)InstanceMethod; ++ (void)ClassMethod; +@end + +@interface ModInterface +@end + +// expected-no-diagnostics + +//--- ExternalModule.h +@interface ExtInterface +@end + +//--- module.modulemap +module ExternalModule { + header "ExternalModule.h" +} + +// RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD +// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" +// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface" +// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface" +// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)Property" +// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod" +// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod" +// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface" +// MOD-DAG: "!testLabel": "c:objc(cs)ModInterface" + +// RUN: FileCheck %s --input-file %t/symbols/ExternalModule@Module.symbols.json --check-prefix EXT +// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" +// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface" +// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface" +// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(py)Property" +// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod" +// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod" +// EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface" +// EXT-NOT: "!testLabel": "c:objc(cs)ModInterface" diff --git a/clang/test/ExtractAPI/objc_id_protocol.m b/clang/test/ExtractAPI/objc_id_protocol.m index 0b0f1b39d2bd61..f2a03a9c575857 100644 --- a/clang/test/ExtractAPI/objc_id_protocol.m +++ b/clang/test/ExtractAPI/objc_id_protocol.m @@ -1,317 +1,56 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o - -verify | FileCheck %s -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h @protocol MyProtocol @end @interface MyInterface @property(copy, readwrite) id obj1; -@property(readwrite) id *obj2; +// CHECK-LABEL: "!testLabel": "c:objc(cs)MyInterface(py)obj1" +// CHECK: "declarationFragments": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "keyword", +// CHECK-NEXT: "spelling": "@property" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " (" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "keyword", +// CHECK-NEXT: "spelling": "copy" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ", " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "keyword", +// CHECK-NEXT: "spelling": "readwrite" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ") " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "typeIdentifier", +// CHECK-NEXT: "preciseIdentifier": "c:Qoobjc(pl)MyProtocol", +// CHECK-NEXT: "spelling": "id" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "identifier", +// CHECK-NEXT: "spelling": "obj1" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ";" +// CHECK-NEXT: } +// CHECK-NEXT: ], @end -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)MyInterface(py)obj1", - "target": "c:objc(cs)MyInterface", - "targetFallback": "MyInterface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)MyInterface(py)obj2", - "target": "c:objc(cs)MyInterface", - "targetFallback": "MyInterface" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyInterface" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)MyInterface" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyInterface" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyInterface" - } - ], - "title": "MyInterface" - }, - "pathComponents": [ - "MyInterface" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "copy" - }, - { - "kind": "text", - "spelling": ", " - }, - { - "kind": "keyword", - "spelling": "readwrite" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:Qoobjc(pl)MyProtocol", - "spelling": "id" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "obj1" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)MyInterface(py)obj1" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 42, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "obj1" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "obj1" - } - ], - "title": "obj1" - }, - "pathComponents": [ - "MyInterface", - "obj1" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "readwrite" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:Qoobjc(pl)MyProtocol", - "spelling": "id" - }, - { - "kind": "text", - "spelling": " * " - }, - { - "kind": "identifier", - "spelling": "obj2" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)MyInterface(py)obj2" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 37, - "line": 5 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "obj2" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "obj2" - } - ], - "title": "obj2" - }, - "pathComponents": [ - "MyInterface", - "obj2" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@protocol" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyProtocol" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)MyProtocol" - }, - "kind": { - "displayName": "Protocol", - "identifier": "objective-c.protocol" - }, - "location": { - "position": { - "character": 10, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyProtocol" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyProtocol" - } - ], - "title": "MyProtocol" - }, - "pathComponents": [ - "MyProtocol" - ] - } - ] -} + +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m index d9d259f2d56028..071ebe440918aa 100644 --- a/clang/test/ExtractAPI/objc_instancetype.m +++ b/clang/test/ExtractAPI/objc_instancetype.m @@ -1,8 +1,8 @@ // RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ - // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify +// RUN: %t/reference.output.json.in >> %t/reference.output.json +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ diff --git a/clang/test/ExtractAPI/objc_interface.m b/clang/test/ExtractAPI/objc_interface.m index ab1772a0c529bb..4abccddc3b5c8e 100644 --- a/clang/test/ExtractAPI/objc_interface.m +++ b/clang/test/ExtractAPI/objc_interface.m @@ -1,701 +1,360 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h -@protocol Protocol; +@protocol Protocol +@end +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SUPER @interface Super +// SUPER: "!testRelLabel": "conformsTo $ c:objc(cs)Super $ c:objc(pl)Protocol" +// SUPER-LABEL: "!testLabel": "c:objc(cs)Super" +// SUPER: "accessLevel": "public", +// SUPER: "declarationFragments": [ +// SUPER-NEXT: { +// SUPER-NEXT: "kind": "keyword", +// SUPER-NEXT: "spelling": "@interface" +// SUPER-NEXT: }, +// SUPER-NEXT: { +// SUPER-NEXT: "kind": "text", +// SUPER-NEXT: "spelling": " " +// SUPER-NEXT: }, +// SUPER-NEXT: { +// SUPER-NEXT: "kind": "identifier", +// SUPER-NEXT: "spelling": "Super" +// SUPER-NEXT: } +// SUPER-NEXT: ], +// SUPER: "kind": { +// SUPER-NEXT: "displayName": "Class", +// SUPER-NEXT: "identifier": "objective-c.class" +// SUPER-NEXT: }, +// SUPER: "title": "Super" +// SUPER: "pathComponents": [ +// SUPER-NEXT: "Super" +// SUPER-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PROP @property(readonly, getter=getProperty) unsigned Property; +// PROP: "!testRelLabel": "memberOf $ c:objc(cs)Super(py)Property $ c:objc(cs)Super" +// PROP: "!testLabel": "c:objc(cs)Super(py)Property" +// PROP: "accessLevel": "public", +// PROP: "declarationFragments": [ +// PROP-NEXT: { +// PROP-NEXT: "kind": "keyword", +// PROP-NEXT: "spelling": "@property" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": " (" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "keyword", +// PROP-NEXT: "spelling": "readonly" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": ", " +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "keyword", +// PROP-NEXT: "spelling": "getter" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": "=" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "identifier", +// PROP-NEXT: "spelling": "getProperty" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": ") " +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "typeIdentifier", +// PROP-NEXT: "preciseIdentifier": "c:i", +// PROP-NEXT: "spelling": "unsigned int" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": " " +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "identifier", +// PROP-NEXT: "spelling": "Property" +// PROP-NEXT: }, +// PROP-NEXT: { +// PROP-NEXT: "kind": "text", +// PROP-NEXT: "spelling": ";" +// PROP-NEXT: } +// PROP-NEXT: ], +// PROP: "kind": { +// PROP-NEXT: "displayName": "Instance Property", +// PROP-NEXT: "identifier": "objective-c.property" +// PROP-NEXT: }, +// PROP: "title": "Property" +// PROP: "pathComponents": [ +// PROP-NEXT: "Super", +// PROP-NEXT: "Property" +// PROP-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GET + (id)getWithProperty:(unsigned) Property; +// GET: "!testRelLabel": "memberOf $ c:objc(cs)Super(cm)getWithProperty: $ c:objc(cs)Super" +// GET-LABEL: "!testLabel": "c:objc(cs)Super(cm)getWithProperty:" +// GET: "accessLevel": "public", +// GET: "declarationFragments": [ +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": "+ (" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "keyword", +// GET-NEXT: "spelling": "id" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": ") " +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "identifier", +// GET-NEXT: "spelling": "getWithProperty:" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": "(" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "typeIdentifier", +// GET-NEXT: "preciseIdentifier": "c:i", +// GET-NEXT: "spelling": "unsigned int" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": ") " +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "internalParam", +// GET-NEXT: "spelling": "Property" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": ";" +// GET-NEXT: } +// GET-NEXT: ], +// GET: "functionSignature": { +// GET-NEXT: "parameters": [ +// GET-NEXT: { +// GET-NEXT: "declarationFragments": [ +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": "(" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "typeIdentifier", +// GET-NEXT: "preciseIdentifier": "c:i", +// GET-NEXT: "spelling": "unsigned int" +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "text", +// GET-NEXT: "spelling": ") " +// GET-NEXT: }, +// GET-NEXT: { +// GET-NEXT: "kind": "internalParam", +// GET-NEXT: "spelling": "Property" +// GET-NEXT: } +// GET-NEXT: ], +// GET-NEXT: "name": "Property" +// GET-NEXT: } +// GET-NEXT: ], +// GET-NEXT: "returns": [ +// GET-NEXT: { +// GET-NEXT: "kind": "keyword", +// GET-NEXT: "spelling": "id" +// GET-NEXT: } +// GET-NEXT: ] +// GET-NEXT: }, +// GET: "kind": { +// GET-NEXT: "displayName": "Type Method", +// GET-NEXT: "identifier": "objective-c.type.method" +// GET-NEXT: }, +// GET: "title": "getWithProperty:" +// GET: "pathComponents": [ +// GET-NEXT: "Super", +// GET-NEXT: "getWithProperty:" +// GET-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SET - (void)setProperty:(unsigned) Property andOtherThing: (unsigned) Thing; +// SET: "!testRelLabel": "memberOf $ c:objc(cs)Super(im)setProperty:andOtherThing: $ c:objc(cs)Super" +// SET-LABEL: "!testLabel": "c:objc(cs)Super(im)setProperty:andOtherThing:" +// SET: "accessLevel": "public", +// SET: "declarationFragments": [ +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": "- (" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:v", +// SET-NEXT: "spelling": "void" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ") " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "identifier", +// SET-NEXT: "spelling": "setProperty:" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": "(" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:i", +// SET-NEXT: "spelling": "unsigned int" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ") " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "internalParam", +// SET-NEXT: "spelling": "Property" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": " " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "identifier", +// SET-NEXT: "spelling": "andOtherThing:" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": "(" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:i", +// SET-NEXT: "spelling": "unsigned int" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ") " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "internalParam", +// SET-NEXT: "spelling": "Thing" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ";" +// SET-NEXT: } +// SET-NEXT: ], +// SET: "functionSignature": { +// SET-NEXT: "parameters": [ +// SET-NEXT: { +// SET-NEXT: "declarationFragments": [ +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": "(" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:i", +// SET-NEXT: "spelling": "unsigned int" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ") " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "internalParam", +// SET-NEXT: "spelling": "Property" +// SET-NEXT: } +// SET-NEXT: ], +// SET-NEXT: "name": "Property" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "declarationFragments": [ +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": "(" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:i", +// SET-NEXT: "spelling": "unsigned int" +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "text", +// SET-NEXT: "spelling": ") " +// SET-NEXT: }, +// SET-NEXT: { +// SET-NEXT: "kind": "internalParam", +// SET-NEXT: "spelling": "Thing" +// SET-NEXT: } +// SET-NEXT: ], +// SET-NEXT: "name": "Thing" +// SET-NEXT: } +// SET-NEXT: ], +// SET-NEXT: "returns": [ +// SET-NEXT: { +// SET-NEXT: "kind": "typeIdentifier", +// SET-NEXT: "preciseIdentifier": "c:v", +// SET-NEXT: "spelling": "void" +// SET-NEXT: } +// SET-NEXT: ] +// SET-NEXT: }, +// SET: "kind": { +// SET-NEXT: "displayName": "Instance Method", +// SET-NEXT: "identifier": "objective-c.method" +// SET-NEXT: }, +// SET: "title": "setProperty:andOtherThing:" @end +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix DERIVED @interface Derived : Super { +// DERIVED: "!testRelLabel": "inheritsFrom $ c:objc(cs)Derived $ c:objc(cs)Super" + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix IVAR char Ivar; +// IVAR: "!testRelLabel": "memberOf $ c:objc(cs)Derived@Ivar $ c:objc(cs)Derived" +// IVAR-LABEL: "!testLabel": "c:objc(cs)Derived@Ivar" +// IVAR: "accessLevel": "public", +// IVAR: "declarationFragments": [ +// IVAR-NEXT: { +// IVAR-NEXT: "kind": "typeIdentifier", +// IVAR-NEXT: "preciseIdentifier": "c:C", +// IVAR-NEXT: "spelling": "char" +// IVAR-NEXT: }, +// IVAR-NEXT: { +// IVAR-NEXT: "kind": "text", +// IVAR-NEXT: "spelling": " " +// IVAR-NEXT: }, +// IVAR-NEXT: { +// IVAR-NEXT: "kind": "identifier", +// IVAR-NEXT: "spelling": "Ivar" +// IVAR-NEXT: }, +// IVAR-NEXT: { +// IVAR-NEXT: "kind": "text", +// IVAR-NEXT: "spelling": ";" +// IVAR-NEXT: } +// IVAR-NEXT: ], +// IVAR: "kind": { +// IVAR-NEXT: "displayName": "Instance Variable", +// IVAR-NEXT: "identifier": "objective-c.ivar" +// IVAR-NEXT: }, +// IVAR: "title": "Ivar" +// IVAR: "pathComponents": [ +// IVAR-NEXT: "Derived", +// IVAR-NEXT: "Ivar" +// IVAR-NEXT: ] } -- (char)getIvar; @end -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)Super(cm)getWithProperty:", - "target": "c:objc(cs)Super", - "targetFallback": "Super" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Super(im)setProperty:andOtherThing:", - "target": "c:objc(cs)Super", - "targetFallback": "Super" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Super(py)Property", - "target": "c:objc(cs)Super", - "targetFallback": "Super" - }, - { - "kind": "conformsTo", - "source": "c:objc(cs)Super", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Derived@Ivar", - "target": "c:objc(cs)Derived", - "targetFallback": "Derived" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Derived(im)getIvar", - "target": "c:objc(cs)Derived", - "targetFallback": "Derived" - }, - { - "kind": "inheritsFrom", - "source": "c:objc(cs)Derived", - "target": "c:objc(cs)Super", - "targetFallback": "Super" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Super" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Super" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Super" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Super" - } - ], - "title": "Super" - }, - "pathComponents": [ - "Super" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "+ (" - }, - { - "kind": "keyword", - "spelling": "id" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "getWithProperty:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Property" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Property" - } - ], - "name": "Property" - } - ], - "returns": [ - { - "kind": "keyword", - "spelling": "id" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Super(cm)getWithProperty:" - }, - "kind": { - "displayName": "Type Method", - "identifier": "objective-c.type.method" - }, - "location": { - "position": { - "character": 0, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "getWithProperty:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "+ " - }, - { - "kind": "identifier", - "spelling": "getWithProperty:" - } - ], - "title": "getWithProperty:" - }, - "pathComponents": [ - "Super", - "getWithProperty:" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "setProperty:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Property" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "andOtherThing:" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Thing" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Property" - } - ], - "name": "Property" - }, - { - "declarationFragments": [ - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "internalParam", - "spelling": "Thing" - } - ], - "name": "Thing" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Super(im)setProperty:andOtherThing:" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 5 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "setProperty:andOtherThing:" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "setProperty:andOtherThing:" - } - ], - "title": "setProperty:andOtherThing:" - }, - "pathComponents": [ - "Super", - "setProperty:andOtherThing:" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "readonly" - }, - { - "kind": "text", - "spelling": ", " - }, - { - "kind": "keyword", - "spelling": "getter" - }, - { - "kind": "text", - "spelling": "=" - }, - { - "kind": "identifier", - "spelling": "getProperty" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Property" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Super(py)Property" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 49, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Property" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Property" - } - ], - "title": "Property" - }, - "pathComponents": [ - "Super", - "Property" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Derived" - }, - { - "kind": "text", - "spelling": " : " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:objc(cs)Super", - "spelling": "Super" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Derived" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Derived" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Derived" - } - ], - "title": "Derived" - }, - "pathComponents": [ - "Derived" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:C", - "spelling": "char" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Ivar" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Derived@Ivar" - }, - "kind": { - "displayName": "Instance Variable", - "identifier": "objective-c.ivar" - }, - "location": { - "position": { - "character": 7, - "line": 9 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Ivar" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Ivar" - } - ], - "title": "Ivar" - }, - "pathComponents": [ - "Derived", - "Ivar" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:C", - "spelling": "char" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "getIvar" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:C", - "spelling": "char" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Derived(im)getIvar" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 11 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "getIvar" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "getIvar" - } - ], - "title": "getIvar" - }, - "pathComponents": [ - "Derived", - "getIvar" - ] - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/objc_module_category.m b/clang/test/ExtractAPI/objc_module_category.m deleted file mode 100644 index 708ed10be821d7..00000000000000 --- a/clang/test/ExtractAPI/objc_module_category.m +++ /dev/null @@ -1,404 +0,0 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header \ -// RUN: -target arm64-apple-macosx \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s - -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h -#import "Foundation.h" - -/// Doc comment 1 -@interface NSString (Category1) --(void)method1; -@end - -/// Doc comment 2 -@interface NSString (Category2) --(void)method2; -@end - -//--- Foundation.h -@interface NSString -@end - -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "extensionTo", - "source": "c:objc(cy)NSString@Category1", - "target": "c:objc(cs)NSString", - "targetFallback": "NSString" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)NSString(im)method1", - "target": "c:objc(cy)NSString@Category1", - "targetFallback": "Category1" - }, - { - "kind": "extensionTo", - "source": "c:objc(cy)NSString@Category2", - "target": "c:objc(cs)NSString", - "targetFallback": "NSString" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)NSString(im)method2", - "target": "c:objc(cy)NSString@Category2", - "targetFallback": "Category2" - } - ], - "symbols": [ - { - "accessLevel": "public", - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category1" - }, - "kind": { - "displayName": "Module Extension", - "identifier": "objective-c.module.extension" - } - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:objc(cs)NSString", - "spelling": "NSString" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "identifier", - "spelling": "Category1" - }, - { - "kind": "text", - "spelling": ")" - } - ], - "docComment": { - "lines": [ - { - "range": { - "end": { - "character": 17, - "line": 2 - }, - "start": { - "character": 4, - "line": 2 - } - }, - "text": "Doc comment 1" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category1" - }, - "kind": { - "displayName": "Class Extension", - "identifier": "objective-c.class.extension" - }, - "location": { - "position": { - "character": 11, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Category1" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Category1" - } - ], - "title": "NSString (Category1)" - }, - "pathComponents": [ - "Category1" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "method1" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)NSString(im)method1" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "method1" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "method1" - } - ], - "title": "method1" - }, - "pathComponents": [ - "Category1", - "method1" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:objc(cs)NSString", - "spelling": "NSString" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "identifier", - "spelling": "Category2" - }, - { - "kind": "text", - "spelling": ")" - } - ], - "docComment": { - "lines": [ - { - "range": { - "end": { - "character": 17, - "line": 7 - }, - "start": { - "character": 4, - "line": 7 - } - }, - "text": "Doc comment 2" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category2" - }, - "kind": { - "displayName": "Class Extension", - "identifier": "objective-c.class.extension" - }, - "location": { - "position": { - "character": 11, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Category2" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Category2" - } - ], - "title": "NSString (Category2)" - }, - "pathComponents": [ - "Category2" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "method2" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)NSString(im)method2" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 9 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "method2" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "method2" - } - ], - "title": "method2" - }, - "pathComponents": [ - "Category2", - "method2" - ] - } - ] -} diff --git a/clang/test/ExtractAPI/objc_property.m b/clang/test/ExtractAPI/objc_property.m index 5712abc15393b6..f05584c885d91f 100644 --- a/clang/test/ExtractAPI/objc_property.m +++ b/clang/test/ExtractAPI/objc_property.m @@ -1,608 +1,26 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -//--- input.h @protocol Protocol @property(class) int myProtocolTypeProp; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(cpy)myProtocolTypeProp $ c:objc(pl)Protocol" @property int myProtocolInstanceProp; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(py)myProtocolInstanceProp $ c:objc(pl)Protocol" @end @interface Interface @property(class) int myInterfaceTypeProp; +// CHECk-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myInterfaceTypeProp $ c:objc(cs)Interface" @property int myInterfaceInstanceProp; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myInterfaceInstanceProp $ c:objc(cs)Interface" @end @interface Interface (Category) @property(class) int myCategoryTypeProp; +// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myCategoryTypeProp $ c:objc(cs)Interface" @property int myCategoryInstanceProp; +// CHECK-DAG "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myCategoryInstanceProp $ c:objc(cs)Interface" @end -// expected-no-diagnostics -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(cpy)myInterfaceTypeProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(py)myInterfaceInstanceProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(cpy)myCategoryTypeProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)Interface(py)myCategoryInstanceProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "conformsTo", - "source": "c:objc(cs)Interface", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" - }, - { - "kind": "memberOf", - "source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" - }, - { - "kind": "memberOf", - "source": "c:objc(pl)Protocol(py)myProtocolInstanceProp", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 5 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Interface" - } - ], - "title": "Interface" - }, - "pathComponents": [ - "Interface" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "class" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myInterfaceTypeProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(cpy)myInterfaceTypeProp" - }, - "kind": { - "displayName": "Type Property", - "identifier": "objective-c.type.property" - }, - "location": { - "position": { - "character": 21, - "line": 6 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myInterfaceTypeProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myInterfaceTypeProp" - } - ], - "title": "myInterfaceTypeProp" - }, - "pathComponents": [ - "Interface", - "myInterfaceTypeProp" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myInterfaceInstanceProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(py)myInterfaceInstanceProp" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 14, - "line": 7 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myInterfaceInstanceProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myInterfaceInstanceProp" - } - ], - "title": "myInterfaceInstanceProp" - }, - "pathComponents": [ - "Interface", - "myInterfaceInstanceProp" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "class" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myCategoryTypeProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp" - }, - "kind": { - "displayName": "Type Property", - "identifier": "objective-c.type.property" - }, - "location": { - "position": { - "character": 21, - "line": 11 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myCategoryTypeProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myCategoryTypeProp" - } - ], - "title": "myCategoryTypeProp" - }, - "pathComponents": [ - "Interface", - "myCategoryTypeProp" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myCategoryInstanceProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(py)myCategoryInstanceProp" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 14, - "line": 12 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myCategoryInstanceProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myCategoryInstanceProp" - } - ], - "title": "myCategoryInstanceProp" - }, - "pathComponents": [ - "Interface", - "myCategoryInstanceProp" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@protocol" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Protocol" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol" - }, - "kind": { - "displayName": "Protocol", - "identifier": "objective-c.protocol" - }, - "location": { - "position": { - "character": 10, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Protocol" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Protocol" - } - ], - "title": "Protocol" - }, - "pathComponents": [ - "Protocol" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "keyword", - "spelling": "class" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myProtocolTypeProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp" - }, - "kind": { - "displayName": "Type Property", - "identifier": "objective-c.type.property" - }, - "location": { - "position": { - "character": 21, - "line": 1 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myProtocolTypeProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myProtocolTypeProp" - } - ], - "title": "myProtocolTypeProp" - }, - "pathComponents": [ - "Protocol", - "myProtocolTypeProp" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "myProtocolInstanceProp" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" - }, - "location": { - "position": { - "character": 14, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "myProtocolInstanceProp" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "myProtocolInstanceProp" - } - ], - "title": "myProtocolInstanceProp" - }, - "pathComponents": [ - "Protocol", - "myProtocolInstanceProp" - ] - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/objc_protocol.m b/clang/test/ExtractAPI/objc_protocol.m index a04936fe041234..06f7ee3d20363e 100644 --- a/clang/test/ExtractAPI/objc_protocol.m +++ b/clang/test/ExtractAPI/objc_protocol.m @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf -x objective-c-header -target arm64-apple-macosx \ // RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/objc_various_categories.m b/clang/test/ExtractAPI/objc_various_categories.m deleted file mode 100644 index adaef5a7b31a99..00000000000000 --- a/clang/test/ExtractAPI/objc_various_categories.m +++ /dev/null @@ -1,507 +0,0 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -x objective-c-header \ -// RUN: -target arm64-apple-macosx \ -// RUN: %t/myclass_1.h \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s - -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h -#import "myclass_1.h" -#import "Foundation.h" - -@interface MyClass1 (MyCategory1) -- (int) SomeMethod; -@end - -@interface NSString (Category1) --(void) StringMethod; -@end - -@interface NSString (Category2) --(void) StringMethod2; -@end - -//--- myclass_1.h -@interface MyClass1 -@end - -//--- Foundation.h -@interface NSString -@end - -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:objc(cs)MyClass1(im)SomeMethod", - "target": "c:objc(cs)MyClass1", - "targetFallback": "MyClass1" - }, - { - "kind": "extensionTo", - "source": "c:objc(cy)NSString@Category1", - "target": "c:objc(cs)NSString", - "targetFallback": "NSString" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)NSString(im)StringMethod", - "target": "c:objc(cy)NSString@Category1", - "targetFallback": "Category1" - }, - { - "kind": "extensionTo", - "source": "c:objc(cy)NSString@Category2", - "target": "c:objc(cs)NSString", - "targetFallback": "NSString" - }, - { - "kind": "memberOf", - "source": "c:objc(cs)NSString(im)StringMethod2", - "target": "c:objc(cy)NSString@Category2", - "targetFallback": "Category2" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyClass1" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)MyClass1" - }, - "kind": { - "displayName": "Class", - "identifier": "objective-c.class" - }, - "location": { - "position": { - "character": 11, - "line": 0 - }, - "uri": "file://INPUT_DIR/myclass_1.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyClass1" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyClass1" - } - ], - "title": "MyClass1" - }, - "pathComponents": [ - "MyClass1" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "SomeMethod" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)MyClass1(im)SomeMethod" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "SomeMethod" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "SomeMethod" - } - ], - "title": "SomeMethod" - }, - "pathComponents": [ - "MyClass1", - "SomeMethod" - ] - }, - { - "accessLevel": "public", - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category1" - }, - "kind": { - "displayName": "Module Extension", - "identifier": "objective-c.module.extension" - } - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:objc(cs)NSString", - "spelling": "NSString" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "identifier", - "spelling": "Category1" - }, - { - "kind": "text", - "spelling": ")" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category1" - }, - "kind": { - "displayName": "Class Extension", - "identifier": "objective-c.class.extension" - }, - "location": { - "position": { - "character": 11, - "line": 7 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Category1" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Category1" - } - ], - "title": "NSString (Category1)" - }, - "pathComponents": [ - "Category1" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "StringMethod" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)NSString(im)StringMethod" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "StringMethod" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "StringMethod" - } - ], - "title": "StringMethod" - }, - "pathComponents": [ - "Category1", - "StringMethod" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@interface" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:objc(cs)NSString", - "spelling": "NSString" - }, - { - "kind": "text", - "spelling": " (" - }, - { - "kind": "identifier", - "spelling": "Category2" - }, - { - "kind": "text", - "spelling": ")" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cy)NSString@Category2" - }, - "kind": { - "displayName": "Class Extension", - "identifier": "objective-c.class.extension" - }, - "location": { - "position": { - "character": 11, - "line": 11 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Category2" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Category2" - } - ], - "title": "NSString (Category2)" - }, - "pathComponents": [ - "Category2" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "text", - "spelling": "- (" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": ") " - }, - { - "kind": "identifier", - "spelling": "StringMethod2" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "functionSignature": { - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)NSString(im)StringMethod2" - }, - "kind": { - "displayName": "Instance Method", - "identifier": "objective-c.method" - }, - "location": { - "position": { - "character": 0, - "line": 12 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "StringMethod2" - } - ], - "subHeading": [ - { - "kind": "text", - "spelling": "- " - }, - { - "kind": "identifier", - "spelling": "StringMethod2" - } - ], - "title": "StringMethod2" - }, - "pathComponents": [ - "Category2", - "StringMethod2" - ] - } - ] -} diff --git a/clang/test/ExtractAPI/operator_overload.cpp b/clang/test/ExtractAPI/operator_overload.cpp index 511a5a7ae8fdf0..9430c58a991e17 100644 --- a/clang/test/ExtractAPI/operator_overload.cpp +++ b/clang/test/ExtractAPI/operator_overload.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/relative_include.m b/clang/test/ExtractAPI/relative_include.m index 46cbdaeeb280c1..e5a02683cbd816 100644 --- a/clang/test/ExtractAPI/relative_include.m +++ b/clang/test/ExtractAPI/relative_include.m @@ -15,7 +15,7 @@ // RUN: %hmaptool write %t/headermap.hmap.json %t/headermap.hmap // Input headers use paths to the framework root/DSTROOT -// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \ // RUN: -triple arm64-apple-macosx \ // RUN: -iquote%t -I%t/headermap.hmap -F%t/Frameworks \ // RUN: -x objective-c-header \ diff --git a/clang/test/ExtractAPI/simple_inheritance.cpp b/clang/test/ExtractAPI/simple_inheritance.cpp index 5fe99afe087633..58c3c4e1e5cb8a 100644 --- a/clang/test/ExtractAPI/simple_inheritance.cpp +++ b/clang/test/ExtractAPI/simple_inheritance.cpp @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ // RUN: -x c++-header %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/struct.c b/clang/test/ExtractAPI/struct.c index 4284b734cd0595..1995a6aedbfd35 100644 --- a/clang/test/ExtractAPI/struct.c +++ b/clang/test/ExtractAPI/struct.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \ // RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/typedef.c b/clang/test/ExtractAPI/typedef.c index c30e65549f2b74..a4c3619bfd210a 100644 --- a/clang/test/ExtractAPI/typedef.c +++ b/clang/test/ExtractAPI/typedef.c @@ -1,391 +1,93 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=Typedef -target arm64-apple-macosx \ -// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT typedef int MyInt; +// MYINT-LABEL: "!testLabel": "c:typedef.c@T@MyInt" +// MYINT: "accessLevel": "public", +// MYINT: "declarationFragments": [ +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "keyword", +// MYINT-NEXT: "spelling": "typedef" +// MYINT-NEXT: }, +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "text", +// MYINT-NEXT: "spelling": " " +// MYINT-NEXT: }, +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "typeIdentifier", +// MYINT-NEXT: "preciseIdentifier": "c:I", +// MYINT-NEXT: "spelling": "int" +// MYINT-NEXT: }, +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "text", +// MYINT-NEXT: "spelling": " " +// MYINT-NEXT: }, +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "identifier", +// MYINT-NEXT: "spelling": "MyInt" +// MYINT-NEXT: }, +// MYINT-NEXT: { +// MYINT-NEXT: "kind": "text", +// MYINT-NEXT: "spelling": ";" +// MYINT-NEXT: } +// MYINT-NEXT: ], +// MYINT: "kind": { +// MYINT-NEXT: "displayName": "Type Alias", +// MYINT-NEXT: "identifier": "objective-c.typealias" +// MYINT-NEXT: }, +// MYINT: "title": "MyInt" +// MYINT: "pathComponents": [ +// MYINT-NEXT: "MyInt" +// MYINT-NEXT: ], +// MYINT: "type": "c:I" +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BARPTR typedef struct Bar *BarPtr; +// BARPTR-LABEL: "!testLabel": "c:typedef.c@T@BarPtr" +// BARPTR: "accessLevel": "public", +// BARPTR: "declarationFragments": [ +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "keyword", +// BARPTR-NEXT: "spelling": "typedef" +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "text", +// BARPTR-NEXT: "spelling": " " +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "keyword", +// BARPTR-NEXT: "spelling": "struct" +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "text", +// BARPTR-NEXT: "spelling": " " +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "typeIdentifier", +// BARPTR-NEXT: "preciseIdentifier": "c:@S@Bar", +// BARPTR-NEXT: "spelling": "Bar" +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "text", +// BARPTR-NEXT: "spelling": " * " +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "identifier", +// BARPTR-NEXT: "spelling": "BarPtr" +// BARPTR-NEXT: }, +// BARPTR-NEXT: { +// BARPTR-NEXT: "kind": "text", +// BARPTR-NEXT: "spelling": ";" +// BARPTR-NEXT: } +// BARPTR-NEXT: ], +// BARPTR: "type": "c:*$@S@Bar" +// RUN: FileCheck %s --input-file %t/output.symbols.json void foo(BarPtr value); void baz(BarPtr *value); +// CHECK-NOT: struct Bar * -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "Typedef", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "foo" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@BarPtr", - "spelling": "BarPtr" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "value" - }, - { - "kind": "text", - "spelling": ");" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@BarPtr", - "spelling": "BarPtr" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "internalParam", - "spelling": "value" - } - ], - "name": "value" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:@F@foo" - }, - "kind": { - "displayName": "Function", - "identifier": "objective-c.func" - }, - "location": { - "position": { - "character": 5, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "foo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "foo" - } - ], - "title": "foo" - }, - "pathComponents": [ - "foo" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "baz" - }, - { - "kind": "text", - "spelling": "(" - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@BarPtr", - "spelling": "BarPtr" - }, - { - "kind": "text", - "spelling": " * " - }, - { - "kind": "internalParam", - "spelling": "value" - }, - { - "kind": "text", - "spelling": ");" - } - ], - "functionSignature": { - "parameters": [ - { - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@BarPtr", - "spelling": "BarPtr" - }, - { - "kind": "text", - "spelling": " * " - }, - { - "kind": "internalParam", - "spelling": "value" - } - ], - "name": "value" - } - ], - "returns": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" - } - ] - }, - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:@F@baz" - }, - "kind": { - "displayName": "Function", - "identifier": "objective-c.func" - }, - "location": { - "position": { - "character": 5, - "line": 6 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "baz" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "baz" - } - ], - "title": "baz" - }, - "pathComponents": [ - "baz" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyInt" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:input.h@T@MyInt" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "objective-c.typealias" - }, - "location": { - "position": { - "character": 12, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyInt" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyInt" - } - ], - "title": "MyInt" - }, - "pathComponents": [ - "MyInt" - ], - "type": "c:I" - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:@S@Bar", - "spelling": "Bar" - }, - { - "kind": "text", - "spelling": " * " - }, - { - "kind": "identifier", - "spelling": "BarPtr" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "objective-c", - "precise": "c:input.h@T@BarPtr" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "objective-c.typealias" - }, - "location": { - "position": { - "character": 20, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "BarPtr" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "BarPtr" - } - ], - "title": "BarPtr" - }, - "pathComponents": [ - "BarPtr" - ], - "type": "c:*$@S@Bar" - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c index 3e4c3e1dd60c4f..9e00ff75254654 100644 --- a/clang/test/ExtractAPI/typedef_anonymous_record.c +++ b/clang/test/ExtractAPI/typedef_anonymous_record.c @@ -1,468 +1,158 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api --product-name=TypedefChain -triple arm64-apple-macosx \ -// RUN: -x c-header %t/input.h -o %t/output.json -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -//--- input.h +// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT typedef struct { } MyStruct; +// MYSTRUCT-LABEL: "!testLabel": "c:@SA@MyStruct" +// MYSTRUCT: "accessLevel": "public", +// MYSTRUCT: "declarationFragments": [ +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "keyword", +// MYSTRUCT-NEXT: "spelling": "typedef" +// MYSTRUCT-NEXT: }, +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "text", +// MYSTRUCT-NEXT: "spelling": " " +// MYSTRUCT-NEXT: }, +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "keyword", +// MYSTRUCT-NEXT: "spelling": "struct" +// MYSTRUCT-NEXT: }, +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "text", +// MYSTRUCT-NEXT: "spelling": " " +// MYSTRUCT-NEXT: }, +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "identifier", +// MYSTRUCT-NEXT: "spelling": "MyStruct" +// MYSTRUCT-NEXT: }, +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT: "kind": "text", +// MYSTRUCT-NEXT: "spelling": ";" +// MYSTRUCT-NEXT: } +// MYSTRUCT-NEXT: ] +// MYSTRUCT: "kind": { +// MYSTRUCT-NEXT: "displayName": "Structure", +// MYSTRUCT-NEXT: "identifier": "c.struct" +// MYSTRUCT: "title": "MyStruct" +// MYSTRUCT: "pathComponents": [ +// MYSTRUCT-NEXT: "MyStruct" +// MYSTRUCT-NEXT: ] + +// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT typedef MyStruct MyStructStruct; -typedef MyStructStruct MyStructStructStruct; +// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyStructStruct" +// MYSTRUCTSTRUCT: "accessLevel": "public", +// MYSTRUCTSTRUCT: "declarationFragments": [ +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "keyword", +// MYSTRUCTSTRUCT-NEXT: "spelling": "typedef" +// MYSTRUCTSTRUCT-NEXT: }, +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "text", +// MYSTRUCTSTRUCT-NEXT: "spelling": " " +// MYSTRUCTSTRUCT-NEXT: }, +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "typeIdentifier", +// MYSTRUCTSTRUCT-NEXT: "preciseIdentifier": "c:@SA@MyStruct", +// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStruct" +// MYSTRUCTSTRUCT-NEXT: }, +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "text", +// MYSTRUCTSTRUCT-NEXT: "spelling": " " +// MYSTRUCTSTRUCT-NEXT: }, +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "identifier", +// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStructStruct" +// MYSTRUCTSTRUCT-NEXT: }, +// MYSTRUCTSTRUCT-NEXT: { +// MYSTRUCTSTRUCT-NEXT: "kind": "text", +// MYSTRUCTSTRUCT-NEXT: "spelling": ";" +// MYSTRUCTSTRUCT-NEXT: } +// MYSTRUCTSTRUCT-NEXT:], +// MYSTRUCTSTRUCT: "kind": { +// MYSTRUCTSTRUCT-NEXT: "displayName": "Type Alias", +// MYSTRUCTSTRUCT-NEXT: "identifier": "c.typealias" + +// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUM +// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix CASE typedef enum { Case } MyEnum; +// MYENUM: "source": "c:@EA@MyEnum@Case", +// MYENUM-NEXT: "target": "c:@EA@MyEnum", +// MYENUM-NEXT: "targetFallback": "MyEnum" +// MYENUM-LABEL: "!testLabel": "c:@EA@MyEnum" +// MYENUM: "declarationFragments": [ +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "keyword", +// MYENUM-NEXT: "spelling": "typedef" +// MYENUM-NEXT: }, +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "text", +// MYENUM-NEXT: "spelling": " " +// MYENUM-NEXT: }, +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "keyword", +// MYENUM-NEXT: "spelling": "enum" +// MYENUM-NEXT: }, +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "text", +// MYENUM-NEXT: "spelling": " " +// MYENUM-NEXT: }, +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "identifier", +// MYENUM-NEXT: "spelling": "MyEnum" +// MYENUM-NEXT: }, +// MYENUM-NEXT: { +// MYENUM-NEXT: "kind": "text", +// MYENUM-NEXT: "spelling": ";" +// MYENUM-NEXT: } +// MYENUM-NEXT:], +// MYENUM: "kind": { +// MYENUM-NEXT: "displayName": "Enumeration", +// MYENUM-NEXT: "identifier": "c.enum" +// MYENUM: "title": "MyEnum" + +// CASE-LABEL: "!testLabel": "c:@EA@MyEnum@Case" +// CASE: "pathComponents": [ +// CASE-NEXT: "MyEnum", +// CASE-NEXT: "Case" +// CASE-NEXT: ] + +// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUMENUM typedef MyEnum MyEnumEnum; -typedef MyEnumEnum MyEnumEnumEnum; -// expected-no-diagnostics +// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyEnumEnum" +// MYENUMENUM: "declarationFragments": [ +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "keyword", +// MYENUMENUM-NEXT: "spelling": "typedef" +// MYENUMENUM-NEXT: }, +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "text", +// MYENUMENUM-NEXT: "spelling": " " +// MYENUMENUM-NEXT: }, +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "typeIdentifier", +// MYENUMENUM-NEXT: "preciseIdentifier": "c:@EA@MyEnum", +// MYENUMENUM-NEXT: "spelling": "MyEnum" +// MYENUMENUM-NEXT: }, +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "text", +// MYENUMENUM-NEXT: "spelling": " " +// MYENUMENUM-NEXT: }, +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "identifier", +// MYENUMENUM-NEXT: "spelling": "MyEnumEnum" +// MYENUMENUM-NEXT: }, +// MYENUMENUM-NEXT: { +// MYENUMENUM-NEXT: "kind": "text", +// MYENUMENUM-NEXT: "spelling": ";" +// MYENUMENUM-NEXT: } +// MYENUMENUM-NEXT: ], +// MYENUMENUM: "kind": { +// MYENUMENUM-NEXT: "displayName": "Type Alias", +// MYENUMENUM-NEXT: "identifier": "c.typealias" +// MYENUMENUM-NEXT: }, +// MYENUMENUM: "title": "MyEnumEnum" -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "TypedefChain", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:@EA@MyEnum@Case", - "target": "c:@EA@MyEnum", - "targetFallback": "MyEnum" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "enum" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyEnum" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@EA@MyEnum" - }, - "kind": { - "displayName": "Enumeration", - "identifier": "c.enum" - }, - "location": { - "position": { - "character": 8, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyEnum" - } - ], - "title": "MyEnum" - }, - "pathComponents": [ - "MyEnum" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "identifier", - "spelling": "Case" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@EA@MyEnum@Case" - }, - "kind": { - "displayName": "Enumeration Case", - "identifier": "c.enum.case" - }, - "location": { - "position": { - "character": 15, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Case" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Case" - } - ], - "title": "Case" - }, - "pathComponents": [ - "MyEnum", - "Case" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyStruct" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@SA@MyStruct" - }, - "kind": { - "displayName": "Structure", - "identifier": "c.struct" - }, - "location": { - "position": { - "character": 8, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyStruct" - } - ], - "title": "MyStruct" - }, - "pathComponents": [ - "MyStruct" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:@SA@MyStruct", - "spelling": "MyStruct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyStructStruct" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@MyStructStruct" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 17, - "line": 1 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyStructStruct" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyStructStruct" - } - ], - "title": "MyStructStruct" - }, - "pathComponents": [ - "MyStructStruct" - ], - "type": "c:@SA@MyStruct" - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@MyStructStruct", - "spelling": "MyStructStruct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyStructStructStruct" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@MyStructStructStruct" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 23, - "line": 2 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyStructStructStruct" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyStructStructStruct" - } - ], - "title": "MyStructStructStruct" - }, - "pathComponents": [ - "MyStructStructStruct" - ], - "type": "c:input.h@T@MyStructStruct" - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:@EA@MyEnum", - "spelling": "MyEnum" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyEnumEnum" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@MyEnumEnum" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 15, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyEnumEnum" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyEnumEnum" - } - ], - "title": "MyEnumEnum" - }, - "pathComponents": [ - "MyEnumEnum" - ], - "type": "c:@EA@MyEnum" - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:input.h@T@MyEnumEnum", - "spelling": "MyEnumEnum" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "MyEnumEnumEnum" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@MyEnumEnumEnum" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 19, - "line": 5 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "MyEnumEnumEnum" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "MyEnumEnumEnum" - } - ], - "title": "MyEnumEnumEnum" - }, - "pathComponents": [ - "MyEnumEnumEnum" - ], - "type": "c:input.h@T@MyEnumEnum" - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/typedef_chain.c b/clang/test/ExtractAPI/typedef_chain.c index 9e6151c8ebd905..05d4eb52cef36b 100644 --- a/clang/test/ExtractAPI/typedef_chain.c +++ b/clang/test/ExtractAPI/typedef_chain.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api --product-name=TypedefChain -target arm64-apple-macosx \ +// RUN: %clang -extract-api --pretty-sgf --product-name=TypedefChain -target arm64-apple-macosx \ // RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. diff --git a/clang/test/ExtractAPI/typedef_struct_enum.c b/clang/test/ExtractAPI/typedef_struct_enum.c index 15357d5b055fb2..fb6fbe987624f8 100644 --- a/clang/test/ExtractAPI/typedef_struct_enum.c +++ b/clang/test/ExtractAPI/typedef_struct_enum.c @@ -1,445 +1,146 @@ // RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang -extract-api -target arm64-apple-macosx \ -// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -x c-header %s -triple arm64-apple-macos -o %t/output.symbols.json -verify -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -// CHECK-NOT: error: -// CHECK-NOT: warning: - -//--- input.h +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST typedef struct Test { } Test; +// TEST-LABEL: "!testLabel": "c:@S@Test" +// TEST: "declarationFragments": [ +// TEST-NEXT: { +// TEST-NEXT: "kind": "keyword", +// TEST-NEXT: "spelling": "typedef" +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "text", +// TEST-NEXT: "spelling": " " +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "keyword", +// TEST-NEXT: "spelling": "struct" +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "text", +// TEST-NEXT: "spelling": " " +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "identifier", +// TEST-NEXT: "spelling": "Test" +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "text", +// TEST-NEXT: "spelling": " { ... } " +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "identifier", +// TEST-NEXT: "spelling": "Test" +// TEST-NEXT: }, +// TEST-NEXT: { +// TEST-NEXT: "kind": "text", +// TEST-NEXT: "spelling": ";" +// TEST-NEXT: } +// TEST-NEXT: ], +// TEST: "displayName": "Structure", +// TEST: "title": "Test" +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST2 typedef enum Test2 { simple } Test2; +// TEST2-LABEL: "!testLabel": "c:@E@Test2" +// TEST2: "declarationFragments": [ +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "keyword", +// TEST2-NEXT: "spelling": "typedef" +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "text", +// TEST2-NEXT: "spelling": " " +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "keyword", +// TEST2-NEXT: "spelling": "enum" +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "text", +// TEST2-NEXT: "spelling": " " +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "identifier", +// TEST2-NEXT: "spelling": "Test2" +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "text", +// TEST2-NEXT: "spelling": ": " +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "typeIdentifier", +// TEST2-NEXT: "preciseIdentifier": "c:i", +// TEST2-NEXT: "spelling": "unsigned int" +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "text", +// TEST2-NEXT: "spelling": " { ... } " +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "identifier", +// TEST2-NEXT: "spelling": "Test2" +// TEST2-NEXT: }, +// TEST2-NEXT: { +// TEST2-NEXT: "kind": "text", +// TEST2-NEXT: "spelling": ";" +// TEST2-NEXT: } +// TEST2-NEXT: ], +// TEST2: "displayName": "Enumeration", +// TEST2: "title": "Test2" + struct Foo; + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPEDEF typedef struct Foo TypedefedFoo; +// TYPEDEF-LABEL: "!testLabel": "c:typedef_struct_enum.c@T@TypedefedFoo" +// TYPEDEF: "declarationFragments": [ +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "keyword", +// TYPEDEF-NEXT: "spelling": "typedef" +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "text", +// TYPEDEF-NEXT: "spelling": " " +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "keyword", +// TYPEDEF-NEXT: "spelling": "struct" +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "text", +// TYPEDEF-NEXT: "spelling": " " +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "typeIdentifier", +// TYPEDEF-NEXT: "preciseIdentifier": "c:@S@Foo", +// TYPEDEF-NEXT: "spelling": "Foo" +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "text", +// TYPEDEF-NEXT: "spelling": " " +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "identifier", +// TYPEDEF-NEXT: "spelling": "TypedefedFoo" +// TYPEDEF-NEXT: }, +// TYPEDEF-NEXT: { +// TYPEDEF-NEXT: "kind": "text", +// TYPEDEF-NEXT: "spelling": ";" +// TYPEDEF-NEXT: } +// TYPEDEF-NEXT: ], +// TYPEDEF: "displayName": "Type Alias", +// TYPEDEF: "title": "TypedefedFoo" +// TYPEDEF: "type": "c:@S@Foo" + struct Foo { int bar; }; -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:@E@Test2@simple", - "target": "c:@E@Test2", - "targetFallback": "Test2" - }, - { - "kind": "memberOf", - "source": "c:@S@Foo@FI@bar", - "target": "c:@S@Foo", - "targetFallback": "Foo" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "enum" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Test2" - }, - { - "kind": "text", - "spelling": ": " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:i", - "spelling": "unsigned int" - }, - { - "kind": "text", - "spelling": " { ... } " - }, - { - "kind": "identifier", - "spelling": "Test2" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@E@Test2" - }, - "kind": { - "displayName": "Enumeration", - "identifier": "c.enum" - }, - "location": { - "position": { - "character": 13, - "line": 3 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Test2" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Test2" - } - ], - "title": "Test2" - }, - "pathComponents": [ - "Test2" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "identifier", - "spelling": "simple" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@E@Test2@simple" - }, - "kind": { - "displayName": "Enumeration Case", - "identifier": "c.enum.case" - }, - "location": { - "position": { - "character": 2, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "simple" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "simple" - } - ], - "title": "simple" - }, - "pathComponents": [ - "Test2", - "simple" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Test" - }, - { - "kind": "text", - "spelling": " { ... } " - }, - { - "kind": "identifier", - "spelling": "Test" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@S@Test" - }, - "kind": { - "displayName": "Structure", - "identifier": "c.struct" - }, - "location": { - "position": { - "character": 15, - "line": 0 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Test" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Test" - } - ], - "title": "Test" - }, - "pathComponents": [ - "Test" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "Foo" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@S@Foo" - }, - "kind": { - "displayName": "Structure", - "identifier": "c.struct" - }, - "location": { - "position": { - "character": 7, - "line": 9 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "Foo" - } - ], - "title": "Foo" - }, - "pathComponents": [ - "Foo" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "bar" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@S@Foo@FI@bar" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "c.property" - }, - "location": { - "position": { - "character": 8, - "line": 10 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "bar" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "bar" - } - ], - "title": "bar" - }, - "pathComponents": [ - "Foo", - "bar" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:@S@Foo", - "spelling": "Foo" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "TypedefedFoo" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@TypedefedFoo" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 19, - "line": 8 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "TypedefedFoo" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "TypedefedFoo" - } - ], - "title": "TypedefedFoo" - }, - "pathComponents": [ - "TypedefedFoo" - ], - "type": "c:@S@Foo" - } - ] -} +// expected-no-diagnostics diff --git a/clang/test/ExtractAPI/underscored.c b/clang/test/ExtractAPI/underscored.c index 30d2b63f763eff..204ec36f1fab1f 100644 --- a/clang/test/ExtractAPI/underscored.c +++ b/clang/test/ExtractAPI/underscored.c @@ -1,17 +1,5 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ -// RUN: %t/reference.output.json.in >> %t/reference.output.json // RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \ -// RUN: -x c-header %t/input.h -o %t/output.json -verify - -// Generator version is not consistent across test runs, normalize it. -// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ -// RUN: %t/output.json >> %t/output-normalized.json -// RUN: diff %t/reference.output.json %t/output-normalized.json - -//--- input.h -// expected-no-diagnostics +// RUN: -x c-header %s -o - -verify | FileCheck %s // Global record int _HiddenGlobal; @@ -19,399 +7,22 @@ int exposed_global; // Record type struct _HiddenRecord { - int a; + int HiddenRecordMember; }; struct ExposedRecord { - int a; + int ExposedRecordMember; }; -// Typedef -typedef struct {} _HiddenTypedef; -typedef int ExposedTypedef; -typedef _HiddenTypedef ExposedTypedefToHidden; - // Macros #define _HIDDEN_MACRO 5 #define EXPOSED_MACRO 5 -// Symbols that start with '_' should not appear in the reference output -//--- reference.output.json.in -{ - "metadata": { - "formatVersion": { - "major": 0, - "minor": 5, - "patch": 3 - }, - "generator": "?" - }, - "module": { - "name": "", - "platform": { - "architecture": "arm64", - "operatingSystem": { - "minimumVersion": { - "major": 11, - "minor": 0, - "patch": 0 - }, - "name": "macosx" - }, - "vendor": "apple" - } - }, - "relationships": [ - { - "kind": "memberOf", - "source": "c:@S@ExposedRecord@FI@a", - "target": "c:@S@ExposedRecord", - "targetFallback": "ExposedRecord" - } - ], - "symbols": [ - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "exposed_global" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@exposed_global" - }, - "kind": { - "displayName": "Global Variable", - "identifier": "c.var" - }, - "location": { - "position": { - "character": 4, - "line": 4 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "exposed_global" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "exposed_global" - } - ], - "title": "exposed_global" - }, - "pathComponents": [ - "exposed_global" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "struct" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "ExposedRecord" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@S@ExposedRecord" - }, - "kind": { - "displayName": "Structure", - "identifier": "c.struct" - }, - "location": { - "position": { - "character": 7, - "line": 11 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "ExposedRecord" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "ExposedRecord" - } - ], - "title": "ExposedRecord" - }, - "pathComponents": [ - "ExposedRecord" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "a" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:@S@ExposedRecord@FI@a" - }, - "kind": { - "displayName": "Instance Property", - "identifier": "c.property" - }, - "location": { - "position": { - "character": 6, - "line": 12 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "a" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "a" - } - ], - "title": "a" - }, - "pathComponents": [ - "ExposedRecord", - "a" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "#define" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "EXPOSED_MACRO" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@335@macro@EXPOSED_MACRO" - }, - "kind": { - "displayName": "Macro", - "identifier": "c.macro" - }, - "location": { - "position": { - "character": 8, - "line": 22 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "EXPOSED_MACRO" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "EXPOSED_MACRO" - } - ], - "title": "EXPOSED_MACRO" - }, - "pathComponents": [ - "EXPOSED_MACRO" - ] - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "ExposedTypedef" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@ExposedTypedef" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 12, - "line": 17 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "ExposedTypedef" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "ExposedTypedef" - } - ], - "title": "ExposedTypedef" - }, - "pathComponents": [ - "ExposedTypedef" - ], - "type": "c:I" - }, - { - "accessLevel": "public", - "declarationFragments": [ - { - "kind": "keyword", - "spelling": "typedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "typeIdentifier", - "preciseIdentifier": "c:@SA@_HiddenTypedef", - "spelling": "_HiddenTypedef" - }, - { - "kind": "text", - "spelling": " " - }, - { - "kind": "identifier", - "spelling": "ExposedTypedefToHidden" - }, - { - "kind": "text", - "spelling": ";" - } - ], - "identifier": { - "interfaceLanguage": "c", - "precise": "c:input.h@T@ExposedTypedefToHidden" - }, - "kind": { - "displayName": "Type Alias", - "identifier": "c.typealias" - }, - "location": { - "position": { - "character": 23, - "line": 18 - }, - "uri": "file://INPUT_DIR/input.h" - }, - "names": { - "navigator": [ - { - "kind": "identifier", - "spelling": "ExposedTypedefToHidden" - } - ], - "subHeading": [ - { - "kind": "identifier", - "spelling": "ExposedTypedefToHidden" - } - ], - "title": "ExposedTypedefToHidden" - }, - "pathComponents": [ - "ExposedTypedefToHidden" - ], - "type": "c:@SA@_HiddenTypedef" - } - ] -} +// expected-no-diagnostics + +// CHECK-NOT: _HiddenRecord +// CHECK-NOT: HiddenRecordMember +// CHECK: ExposedRecord +// CHECK: ExposedRecordMember +// CHECK-NOT: _HIDDEN_MACRO +// CHECK: EXPOSED_MACRO diff --git a/clang/test/ExtractAPI/union.c b/clang/test/ExtractAPI/union.c index 6ec9fd3ddf6e99..8f8300b2c9a52d 100644 --- a/clang/test/ExtractAPI/union.c +++ b/clang/test/ExtractAPI/union.c @@ -2,7 +2,7 @@ // RUN: split-file %s %t // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/reference.output.json.in >> %t/reference.output.json -// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x c-header\ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x c-header\ // RUN: %t/input.h -o %t/output.json -verify // Generator version is not consistent across test runs, normalize it. @@ -12,7 +12,7 @@ //--- input.h /// My Union -union Union{ +union Union { /// the a option int a; /// the b option diff --git a/clang/test/ExtractAPI/vfs_redirected_include.m b/clang/test/ExtractAPI/vfs_redirected_include.m index 9ba7e1dedb601e..db0382052ba3ef 100644 --- a/clang/test/ExtractAPI/vfs_redirected_include.m +++ b/clang/test/ExtractAPI/vfs_redirected_include.m @@ -14,7 +14,7 @@ // RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml // Input headers use paths to the framework root/DSTROOT -// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \ +// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \ // RUN: -triple arm64-apple-macosx \ // RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \ // RUN: -x objective-c-header \ diff --git a/clang/test/Index/extract-api-cursor.m b/clang/test/Index/extract-api-cursor.m index 1b27b6f61437be..9d9d3a1e40f145 100644 --- a/clang/test/Index/extract-api-cursor.m +++ b/clang/test/Index/extract-api-cursor.m @@ -31,6 +31,8 @@ @implementation Derived - (void)derivedMethodWithValue:(id)value { int a = 5; } +/// Impl only docs +- (void)implOnlyMethod { } @end // RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s @@ -118,3 +120,10 @@ - (void)derivedMethodWithValue:(id)value { // CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs" // CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} // CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:" + +// RUN: c-index-test -single-symbol-sgf-at=%s:35:11 local %s | FileCheck -check-prefix=CHECK-IMPL-ONLY %s +// CHECK-IMPL-ONLY: "relatedSymbols":[] +// CHECK-IMPL-ONLY: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)implOnlyMethod","target":"c:objc(cs)Derived" +// CHECK-IMPL-ONLY: "text":"Impl only docs" +// CHECK-IMPL-ONLY: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} +// CHECK-IMPL-ONLY: "title":"implOnlyMethod" diff --git a/clang/test/InstallAPI/diagnostics-dsym.test b/clang/test/InstallAPI/diagnostics-dsym.test index 8a1b394f2f8683..c9cbeffef7bacc 100644 --- a/clang/test/InstallAPI/diagnostics-dsym.test +++ b/clang/test/InstallAPI/diagnostics-dsym.test @@ -1,23 +1,24 @@ -; REQUIRES: 86_64-darwin +; REQUIRES: system-darwin +; REQUIRES: target-aarch64 ; RUN: rm -rf %t ; RUN: split-file %s %t // Build a simple dylib with debug info. -; RUN: %clang --target=x86_64-apple-macos10.15 -g -dynamiclib %t/foo.c \ +; RUN: %clang --target=arm64-apple-macos11 -g -dynamiclib %t/foo.c \ ; RUN: -current_version 1 -compatibility_version 1 -L%t/usr/lib \ ; RUN: -save-temps \ ; RUN: -o %t/foo.dylib -install_name %t/foo.dylib ; RUN: dsymutil %t/foo.dylib -o %t/foo.dSYM -; RUN: not clang-installapi -x c++ --target=x86_64-apple-macos10.15 \ +; RUN: not clang-installapi -x c++ --target=arm64-apple-macos11 \ ; RUN: -install_name %t/foo.dylib \ ; RUN: -current_version 1 -compatibility_version 1 \ ; RUN: -o %t/output.tbd \ ; RUN: --verify-against=%t/foo.dylib --dsym=%t/foo.dSYM \ ; RUN: --verify-mode=Pedantic 2>&1 | FileCheck %s -; CHECK: violations found for x86_64 +; CHECK: violations found for arm64 ; CHECK: foo.c:5:0: error: no declaration found for exported symbol 'bar' in dynamic library ; CHECK: foo.c:1:0: error: no declaration found for exported symbol 'foo' in dynamic library @@ -31,9 +32,9 @@ char bar = 'a'; ;--- usr/lib/libSystem.tbd --- !tapi-tbd tbd-version: 4 -targets: [ x86_64-macos ] +targets: [ arm64-macos ] install-name: '/usr/lib/libSystem.B.dylib' exports: - - targets: [ x86_64-macos ] + - targets: [ arm64-macos ] symbols: [ dyld_stub_binder ] ... diff --git a/clang/test/Modules/language-linkage.cppm b/clang/test/Modules/language-linkage.cppm index bf7982cd9207d6..a5db9e9ebc07ec 100644 --- a/clang/test/Modules/language-linkage.cppm +++ b/clang/test/Modules/language-linkage.cppm @@ -14,5 +14,5 @@ void foo() {} extern "C" void bar() {} -// CHECK: define {{.*}}@bar( // CHECK: define {{.*}}@_Z3foov( +// CHECK: define {{.*}}@bar( diff --git a/clang/test/Modules/reduced-bmi-size.cppm b/clang/test/Modules/reduced-bmi-size.cppm new file mode 100644 index 00000000000000..664f45f5c6a5a7 --- /dev/null +++ b/clang/test/Modules/reduced-bmi-size.cppm @@ -0,0 +1,16 @@ +// Ensure that the size of the reduced BMI is not larger than the full BMI +// in the most simple case. + +// This test requires linux commands. +// REQUIRES: system-linux + +// RUN: rm -fr %t +// RUN: mkdir %t +// +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %s -o %t/a.reduced.pcm +// +// %s implies the current source file. So we can't use it directly. +// RUN: [ $(stat -c%\s "%t/a.pcm") -le $(stat -c%\s "%t/a.reduced.pcm") ] + +export module a; diff --git a/clang/test/Sema/GH70594.cpp b/clang/test/Sema/GH70594.cpp new file mode 100644 index 00000000000000..ce98e9b12b5cba --- /dev/null +++ b/clang/test/Sema/GH70594.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++23 %s -verify + +// expected-no-diagnostics + +struct A {}; +using CA = const A; + +struct S1 : CA { + constexpr S1() : CA() {} +}; + +struct S2 : A { + constexpr S2() : CA() {} +}; + +struct S3 : CA { + constexpr S3() : A() {} +}; + +struct Int {}; + +template +struct __tuple_leaf : _Hp { + constexpr __tuple_leaf() : _Hp() {} +}; + +constexpr __tuple_leaf t; diff --git a/clang/test/Sema/code_align.c b/clang/test/Sema/code_align.c index d494d5ea1558f0..f01f51382112f4 100644 --- a/clang/test/Sema/code_align.c +++ b/clang/test/Sema/code_align.c @@ -62,6 +62,17 @@ void foo1(int A) [[clang::code_align(64)]] // expected-error{{conflicting loop attribute 'code_align'}} for(int I=0; I<128; ++I) { bar(I); } + [[clang::code_align(4)]] // expected-note{{previous attribute is here}} + [[clang::code_align(4)]] // OK + [[clang::code_align(8)]] // expected-error{{conflicting loop attribute 'code_align'}} + for(int I=0; I<128; ++I) { bar(I); } + + [[clang::code_align(4)]] // expected-note 2{{previous attribute is here}} + [[clang::code_align(4)]] // OK + [[clang::code_align(8)]] // expected-error{{conflicting loop attribute 'code_align'}} + [[clang::code_align(64)]] // expected-error{{conflicting loop attribute 'code_align'}} + for(int I=0; I<128; ++I) { bar(I); } + // expected-error@+1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 7}} [[clang::code_align(7)]] for(int I=0; I<128; ++I) { bar(I); } @@ -135,6 +146,17 @@ void code_align_dependent() { [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}} for(int I=0; I<128; ++I) { bar(I); } + [[clang::code_align(A)]] // cpp-local-note{{previous attribute is here}} + [[clang::code_align(A)]] // OK + [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}} + for(int I=0; I<128; ++I) { bar(I); } + + [[clang::code_align(A)]] // cpp-local-note 2{{previous attribute is here}} + [[clang::code_align(A)]] // OK + [[clang::code_align(C)]] // cpp-local-error{{conflicting loop attribute 'code_align'}} + [[clang::code_align(E)]] // cpp-local-error{{conflicting loop attribute 'code_align'}} + for(int I=0; I<128; ++I) { bar(I); } + // cpp-local-error@+1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was 23}} [[clang::code_align(B)]] for(int I=0; I<128; ++I) { bar(I); } diff --git a/clang/test/Sema/nullability.c b/clang/test/Sema/nullability.c index 7d193bea46771f..0401516233b6db 100644 --- a/clang/test/Sema/nullability.c +++ b/clang/test/Sema/nullability.c @@ -248,3 +248,5 @@ void arraysInBlocks(void) { void (^withTypedefBad)(INTS _Nonnull [2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} ^(INTS _Nonnull x[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} } + +struct _Nullable NotCplusplusClass {}; // expected-error {{'_Nullable' attribute only applies to classes}} diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index ce403285b0f531..b71cd46f884d63 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -259,3 +259,23 @@ using Bar2 = Foo; // expected-error {{extraneous template parameter list in a Bar2 b = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} } // namespace test19 + +// GH85385 +namespace test20 { +template