170 changes: 138 additions & 32 deletions clang-tools-extra/clangd/HeuristicResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,80 @@
namespace clang {
namespace clangd {

namespace {

// Helper class for implementing HeuristicResolver.
// Unlike HeuristicResolver which is a long-lived class,
// a new instance of this class is created for every external
// call into a HeuristicResolver operation. That allows this
// class to store state that's local to such a top-level call,
// particularly "recursion protection sets" that keep track of
// nodes that have already been seen to avoid infinite recursion.
class HeuristicResolverImpl {
public:
HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {}

// These functions match the public interface of HeuristicResolver
// (but aren't const since they may modify the recursion protection sets).
std::vector<const NamedDecl *>
resolveMemberExpr(const CXXDependentScopeMemberExpr *ME);
std::vector<const NamedDecl *>
resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE);
std::vector<const NamedDecl *> resolveTypeOfCallExpr(const CallExpr *CE);
std::vector<const NamedDecl *> resolveCalleeOfCallExpr(const CallExpr *CE);
std::vector<const NamedDecl *>
resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD);
std::vector<const NamedDecl *>
resolveDependentNameType(const DependentNameType *DNT);
std::vector<const NamedDecl *> resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST);
const Type *resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
const Type *getPointeeType(const Type *T);

private:
ASTContext &Ctx;

// Recursion protection sets
llvm::SmallSet<const DependentNameType *, 4> SeenDependentNameTypes;

// Given a tag-decl type and a member name, heuristically resolve the
// name to one or more declarations.
// The current heuristic is simply to look up the name in the primary
// template. This is a heuristic because the template could potentially
// have specializations that declare different members.
// Multiple declarations could be returned if the name is overloaded
// (e.g. an overloaded method in the primary template).
// This heuristic will give the desired answer in many cases, e.g.
// for a call to vector<T>::size().
std::vector<const NamedDecl *>
resolveDependentMember(const Type *T, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter);

// Try to heuristically resolve the type of a possibly-dependent expression
// `E`.
const Type *resolveExprToType(const Expr *E);
std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E);

// Helper function for HeuristicResolver::resolveDependentMember()
// which takes a possibly-dependent type `T` and heuristically
// resolves it to a CXXRecordDecl in which we can try name lookup.
CXXRecordDecl *resolveTypeToRecordDecl(const Type *T);

// This is a reimplementation of CXXRecordDecl::lookupDependentName()
// so that the implementation can call into other HeuristicResolver helpers.
// FIXME: Once HeuristicResolver is upstreamed to the clang libraries
// (https://github.com/clangd/clangd/discussions/1662),
// CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites
// can be modified to benefit from the more comprehensive heuristics offered
// by HeuristicResolver instead.
std::vector<const NamedDecl *>
lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter);
bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
DeclarationName Name);
};

// Convenience lambdas for use as the 'Filter' parameter of
// HeuristicResolver::resolveDependentMember().
const auto NoFilter = [](const NamedDecl *D) { return true; };
Expand All @@ -31,8 +105,6 @@ const auto TemplateFilter = [](const NamedDecl *D) {
return isa<TemplateDecl>(D);
};

namespace {

const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
ASTContext &Ctx) {
if (Decls.size() != 1) // Names an overload set -- just bail.
Expand All @@ -46,12 +118,10 @@ const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
return nullptr;
}

} // namespace

// Helper function for HeuristicResolver::resolveDependentMember()
// which takes a possibly-dependent type `T` and heuristically
// resolves it to a CXXRecordDecl in which we can try name lookup.
CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const {
CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
assert(T);

// Unwrap type sugar such as type aliases.
Expand Down Expand Up @@ -84,7 +154,7 @@ CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const {
return TD->getTemplatedDecl();
}

const Type *HeuristicResolver::getPointeeType(const Type *T) const {
const Type *HeuristicResolverImpl::getPointeeType(const Type *T) {
if (!T)
return nullptr;

Expand Down Expand Up @@ -117,8 +187,8 @@ const Type *HeuristicResolver::getPointeeType(const Type *T) const {
return FirstArg.getAsType().getTypePtrOrNull();
}

std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME) const {
std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME) {
// If the expression has a qualifier, try resolving the member inside the
// qualifier's type.
// Note that we cannot use a NonStaticFilter in either case, for a couple
Expand Down Expand Up @@ -164,14 +234,14 @@ std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
}

std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) const {
std::vector<const NamedDecl *>
HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) {
return resolveDependentMember(RE->getQualifier()->getAsType(),
RE->getDeclName(), StaticFilter);
}

std::vector<const NamedDecl *>
HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
const auto *CalleeType = resolveExprToType(CE->getCallee());
if (!CalleeType)
return {};
Expand All @@ -187,37 +257,39 @@ HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
}

std::vector<const NamedDecl *>
HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) {
if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
return {ND};
}

return resolveExprToDecls(CE->getCallee());
}

std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) const {
std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) {
return resolveDependentMember(UUVD->getQualifier()->getAsType(),
UUVD->getNameInfo().getName(), ValueFilter);
}

std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
const DependentNameType *DNT) const {
std::vector<const NamedDecl *>
HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) {
if (auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted)
return {};
return resolveDependentMember(
resolveNestedNameSpecifierToType(DNT->getQualifier()),
DNT->getIdentifier(), TypeFilter);
}

std::vector<const NamedDecl *>
HeuristicResolver::resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST) const {
HeuristicResolverImpl::resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST) {
return resolveDependentMember(
resolveNestedNameSpecifierToType(DTST->getQualifier()),
DTST->getIdentifier(), TemplateFilter);
}

std::vector<const NamedDecl *>
HeuristicResolver::resolveExprToDecls(const Expr *E) const {
HeuristicResolverImpl::resolveExprToDecls(const Expr *E) {
if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
return resolveMemberExpr(ME);
}
Expand All @@ -236,16 +308,16 @@ HeuristicResolver::resolveExprToDecls(const Expr *E) const {
return {};
}

const Type *HeuristicResolver::resolveExprToType(const Expr *E) const {
const Type *HeuristicResolverImpl::resolveExprToType(const Expr *E) {
std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
if (!Decls.empty())
return resolveDeclsToType(Decls, Ctx);

return E->getType().getTypePtr();
}

const Type *HeuristicResolver::resolveNestedNameSpecifierToType(
const NestedNameSpecifier *NNS) const {
const Type *HeuristicResolverImpl::resolveNestedNameSpecifierToType(
const NestedNameSpecifier *NNS) {
if (!NNS)
return nullptr;

Expand All @@ -270,8 +342,6 @@ const Type *HeuristicResolver::resolveNestedNameSpecifierToType(
return nullptr;
}

namespace {

bool isOrdinaryMember(const NamedDecl *ND) {
return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
Decl::IDNS_Member);
Expand All @@ -287,21 +357,19 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
return false;
}

} // namespace

bool HeuristicResolver::findOrdinaryMemberInDependentClasses(
bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
DeclarationName Name) const {
DeclarationName Name) {
CXXRecordDecl *RD =
resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
if (!RD)
return false;
return findOrdinaryMember(RD, Path, Name);
}

std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
CXXRecordDecl *RD, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter) const {
llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
std::vector<const NamedDecl *> Results;

// Lookup in the class.
Expand Down Expand Up @@ -332,9 +400,9 @@ std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
return Results;
}

std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember(
std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
const Type *T, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter) const {
llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
if (!T)
return {};
if (auto *ET = T->getAs<EnumType>()) {
Expand All @@ -349,6 +417,44 @@ std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember(
}
return {};
}
} // namespace

std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr(
const CXXDependentScopeMemberExpr *ME) const {
return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME);
}
std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr(
const DependentScopeDeclRefExpr *RE) const {
return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE);
}
std::vector<const NamedDecl *>
HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE);
}
std::vector<const NamedDecl *>
HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE);
}
std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) const {
return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD);
}
std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType(
const DependentNameType *DNT) const {
return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT);
}
std::vector<const NamedDecl *>
HeuristicResolver::resolveTemplateSpecializationType(
const DependentTemplateSpecializationType *DTST) const {
return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
}
const Type *HeuristicResolver::resolveNestedNameSpecifierToType(
const NestedNameSpecifier *NNS) const {
return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
}
const Type *HeuristicResolver::getPointeeType(const Type *T) const {
return HeuristicResolverImpl(Ctx).getPointeeType(T);
}

} // namespace clangd
} // namespace clang
37 changes: 0 additions & 37 deletions clang-tools-extra/clangd/HeuristicResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,43 +77,6 @@ class HeuristicResolver {

private:
ASTContext &Ctx;

// Given a tag-decl type and a member name, heuristically resolve the
// name to one or more declarations.
// The current heuristic is simply to look up the name in the primary
// template. This is a heuristic because the template could potentially
// have specializations that declare different members.
// Multiple declarations could be returned if the name is overloaded
// (e.g. an overloaded method in the primary template).
// This heuristic will give the desired answer in many cases, e.g.
// for a call to vector<T>::size().
std::vector<const NamedDecl *> resolveDependentMember(
const Type *T, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter) const;

// Try to heuristically resolve the type of a possibly-dependent expression
// `E`.
const Type *resolveExprToType(const Expr *E) const;
std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E) const;

// Helper function for HeuristicResolver::resolveDependentMember()
// which takes a possibly-dependent type `T` and heuristically
// resolves it to a CXXRecordDecl in which we can try name lookup.
CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const;

// This is a reimplementation of CXXRecordDecl::lookupDependentName()
// so that the implementation can call into other HeuristicResolver helpers.
// FIXME: Once HeuristicResolver is upstreamed to the clang libraries
// (https://github.com/clangd/clangd/discussions/1662),
// CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites
// can be modified to benefit from the more comprehensive heuristics offered
// by HeuristicResolver instead.
std::vector<const NamedDecl *> lookupDependentName(
CXXRecordDecl *RD, DeclarationName Name,
llvm::function_ref<bool(const NamedDecl *ND)> Filter) const;
bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
DeclarationName Name) const;
};

} // namespace clangd
Expand Down
27 changes: 27 additions & 0 deletions clang-tools-extra/clangd/unittests/FindTargetTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,33 @@ TEST_F(TargetDeclTest, DependentTypes) {
)cpp";
EXPECT_DECLS("DependentTemplateSpecializationTypeLoc",
"template <typename> struct B");

// Dependent name with recursive definition. We don't expect a
// result, but we shouldn't get into a stack overflow either.
Code = R"cpp(
template <int N>
struct waldo {
typedef typename waldo<N - 1>::type::[[next]] type;
};
)cpp";
EXPECT_DECLS("DependentNameTypeLoc");

// Similar to above but using mutually recursive templates.
Code = R"cpp(
template <int N>
struct odd;
template <int N>
struct even {
using type = typename odd<N - 1>::type::next;
};
template <int N>
struct odd {
using type = typename even<N - 1>::type::[[next]];
};
)cpp";
EXPECT_DECLS("DependentNameTypeLoc");
}

TEST_F(TargetDeclTest, TypedefCascade) {
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ Changes in existing checks
<clang-tidy/checks/google/build-namespaces>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`google-explicit-constructor
<clang-tidy/checks/google/explicit-constructor>` check to better handle
``C++-20`` `explicit(bool)`.

- Improved :doc:`google-global-names-in-headers
<clang-tidy/checks/google/global-names-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: %check_clang_tidy %s google-explicit-constructor %t -std=c++20-or-later

namespace issue_81121
{

static constexpr bool ConstFalse = false;
static constexpr bool ConstTrue = true;

struct A {
explicit(true) A(int);
};

struct B {
explicit(false) B(int);
};

struct C {
explicit(ConstTrue) C(int);
};

struct D {
explicit(ConstFalse) D(int);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor]
};

template <typename>
struct E {
explicit(true) E(int);
};

template <typename>
struct F {
explicit(false) F(int);
};

template <typename>
struct G {
explicit(ConstTrue) G(int);
};

template <typename>
struct H {
explicit(ConstFalse) H(int);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor]
};

template <int Val>
struct I {
explicit(Val > 0) I(int);
};

template <int Val>
struct J {
explicit(Val > 0) J(int);
};

void useJ(J<0>, J<100>);

} // namespace issue_81121
102 changes: 48 additions & 54 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ C/C++ Language Potentially Breaking Changes

C++ Specific Potentially Breaking Changes
-----------------------------------------
- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``.
This error can be disabled via `-Wno-strict-primary-template-shadow` for compatibility with previous versions of clang.

ABI Changes in This Version
---------------------------
Expand Down Expand Up @@ -79,7 +81,7 @@ C++20 Feature Support
more to ease the implementation and improve the user's using experience.
This follows the MSVC's behavior. Users interested in testing the more strict
behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
(`#79240 <https://github.com/llvm/llvm-project/issues/79240>`_).
(#GH79240).

- Implemented the `__is_layout_compatible` intrinsic to support
`P0466R5: Layout-compatibility and Pointer-interconvertibility Traits <https://wg21.link/P0466R5>`_.
Expand Down Expand Up @@ -116,7 +118,7 @@ C Language Changes
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
- No longer diagnose use of binary literals as an extension in C23 mode. Fixes
`#72017 <https://github.com/llvm/llvm-project/issues/72017>`_.
#GH72017.

- Corrected parsing behavior for the ``alignas`` specifier/qualifier in C23. We
previously handled it as an attribute as in C++, but there are parsing
Expand All @@ -129,7 +131,7 @@ C23 Feature Support
};
int i alignas(8) /* was accepted, now rejected */ ;
Fixes (`#81472 <https://github.com/llvm/llvm-project/issues/81472>`_).
Fixes (#GH81472).

- Clang now generates predefined macros of the form ``__TYPE_FMTB__`` and
``__TYPE_FMTb__`` (e.g., ``__UINT_FAST64_FMTB__``) in C23 mode for use with
Expand Down Expand Up @@ -173,7 +175,7 @@ Improvements to Clang's diagnostics
name specifiers.

- The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead
of ``-Wconversion``. Fixes `#69444 <https://github.com/llvm/llvm-project/issues/69444>`_.
of ``-Wconversion``. Fixes #GH69444.

- Clang now diagnoses friend declarations with an ``enum`` elaborated-type-specifier in language modes after C++98.

Expand All @@ -186,14 +188,14 @@ Improvements to Clang's diagnostics
``unsigned long long``, but this behavior may change in the future when Clang
implements
`WG14 N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm>`_.
Fixes `#69352 <https://github.com/llvm/llvm-project/issues/69352>`_.
(#GH69352).

- Clang now diagnoses extraneous template parameter lists as a language extension.

- Clang now diagnoses declarative nested name specifiers that name alias templates.

- Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``.
Fixes `#82512 <https://github.com/llvm/llvm-project/issues/82512>`_.
Fixes #GH82512.

Improvements to Clang's time-trace
----------------------------------
Expand All @@ -206,21 +208,21 @@ Bug Fixes in This Version
- Clang now accepts elaborated-type-specifiers that explicitly specialize
a member class template for an implicit instantiation of a class template.

- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 <https://github.com/llvm/llvm-project/issues/79435>`_).
- Fixed missing warnings when doing bool-like conversions in C23 (#GH79435).
- Clang's ``-Wshadow`` no longer warns when an init-capture is named the same as
a class field unless the lambda can capture this.
Fixes (`#71976 <https://github.com/llvm/llvm-project/issues/71976>`_)
Fixes (#GH71976)

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

- Clang now doesn't produce false-positive warning `-Wconstant-logical-operand`
for logical operators in C23.
Fixes (`#64356 <https://github.com/llvm/llvm-project/issues/64356>`_).
Fixes (#GH64356).

- Clang no longer produces a false-positive `-Wunused-variable` warning
for variables created through copy initialization having side-effects in C++17 and later.
Fixes (`#79518 <https://github.com/llvm/llvm-project/issues/79518>`_).
Fixes (#GH64356) (#GH79518).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -232,84 +234,67 @@ Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^

- Fix crash when calling the constructor of an invalid class.
Fixes (`#10518 <https://github.com/llvm/llvm-project/issues/10518>`_),
(`#67914 <https://github.com/llvm/llvm-project/issues/10518>`_),
and (`#78388 <https://github.com/llvm/llvm-project/issues/78388>`_)
(#GH10518) (#GH67914) (#GH78388)
- Fix crash when using lifetimebound attribute in function with trailing return.
Fixes (`#73619 <https://github.com/llvm/llvm-project/issues/73619>`_)
(#GH73619)
- Addressed an issue where constraints involving injected class types are perceived
distinct from its specialization types.
(`#56482 <https://github.com/llvm/llvm-project/issues/56482>`_)
distinct from its specialization types. (#GH56482)
- Fixed a bug where variables referenced by requires-clauses inside
nested generic lambdas were not properly injected into the constraint scope.
(`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)
nested generic lambdas were not properly injected into the constraint scope. (#GH73418)
- Fixed a crash where substituting into a requires-expression that refers to function
parameters during the equivalence determination of two constraint expressions.
(`#74447 <https://github.com/llvm/llvm-project/issues/74447>`_)
(#GH74447)
- Fixed deducing auto& from const int in template parameters of partial
specializations.
(`#77189 <https://github.com/llvm/llvm-project/issues/77189>`_)
specializations. (#GH77189)
- Fix for crash when using a erroneous type in a return statement.
Fixes (`#63244 <https://github.com/llvm/llvm-project/issues/63244>`_)
and (`#79745 <https://github.com/llvm/llvm-project/issues/79745>`_)
(#GH63244) (#GH79745)
- Fixed an out-of-bounds error caused by building a recovery expression for ill-formed
function calls while substituting into constraints.
(`#58548 <https://github.com/llvm/llvm-project/issues/58548>`_)
- Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
function calls while substituting into constraints. (#GH58548)
- Fix incorrect code generation caused by the object argument
of ``static operator()`` and ``static operator[]`` calls not being evaluated. (#GH67976)
- Fix crash and diagnostic with const qualified member operator new.
Fixes (`#79748 <https://github.com/llvm/llvm-project/issues/79748>`_)
Fixes (#GH79748)
- Fixed a crash where substituting into a requires-expression that involves parameter packs
during the equivalence determination of two constraint expressions.
(`#72557 <https://github.com/llvm/llvm-project/issues/72557>`_)
during the equivalence determination of two constraint expressions. (#GH72557)
- Fix a crash when specializing an out-of-line member function with a default
parameter where we did an incorrect specialization of the initialization of
the default parameter.
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)
the default parameter. (#GH68490)
- Fix a crash when trying to call a varargs function that also has an explicit object parameter.
Fixes (`#80971 ICE when explicit object parameter be a function parameter pack`)
- Reject explicit object parameters on `new` and `delete` operators.
Fixes (`#82249 <https://github.com/llvm/llvm-project/issues/82249>` _)
Fixes (#GH80971)
- Reject explicit object parameters on `new` and `delete` operators. (#GH82249)
- Fix a crash when trying to call a varargs function that also has an explicit object parameter. (#GH80971)
- Fixed a bug where abbreviated function templates would append their invented template parameters to
an empty template parameter lists.
- Clang now classifies aggregate initialization in C++17 and newer as constant
or non-constant more accurately. Previously, only a subset of the initializer
elements were considered, misclassifying some initializers as constant. Fixes
some of (`#80510 <https://github.com/llvm/llvm-project/issues/80510>`).
- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings.
(`#75404 <https://github.com/llvm/llvm-project/issues/75404>`_)
elements were considered, misclassifying some initializers as constant. Partially fixes
#GH80510.
- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings. (#GH75404)
- No longer reject valid use of the ``_Alignas`` specifier when declaring a
local variable, which is supported as a C11 extension in C++. Previously, it
was only accepted at namespace scope but not at local function scope.
- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer.
(`#82154 <https://github.com/llvm/llvm-project/issues/82154>`_`)
- Fix crash when using an immediate-escalated function at global scope.
(`#82258 <https://github.com/llvm/llvm-project/issues/82258>`_)
- Correctly immediate-escalate lambda conversion functions.
(`#82258 <https://github.com/llvm/llvm-project/issues/82258>`_)
- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer. (#GH82154)
- Fix crash when using an immediate-escalated function at global scope. (#GH82258)
- Correctly immediate-escalate lambda conversion functions. (#GH82258)
- Fixed an issue where template parameters of a nested abbreviated generic lambda within
a requires-clause lie at the same depth as those of the surrounding lambda. This,
in turn, results in the wrong template argument substitution during constraint checking.
(`#78524 <https://github.com/llvm/llvm-project/issues/78524>`_)
(#GH78524)
- Clang no longer instantiates the exception specification of discarded candidate function
templates when determining the primary template of an explicit specialization.
- Fixed a crash in Microsoft compatibility mode where unqualified dependent base class
lookup searches the bases of an incomplete class.
- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator.
(`#53815 <https://github.com/llvm/llvm-project/issues/53815>`_)
(#GH53815)
- In ``__restrict``-qualified member functions, attach ``__restrict`` to the pointer type of
``this`` rather than the pointee type.
Fixes (`#82941 <https://github.com/llvm/llvm-project/issues/82941>`_),
(`#42411 <https://github.com/llvm/llvm-project/issues/42411>`_), and
(`#18121 <https://github.com/llvm/llvm-project/issues/18121>`_).
Fixes (#GH82941), (#GH42411) and (#GH18121).
- Clang now properly reports supported C++11 attributes when using
``__has_cpp_attribute`` and parses attributes with arguments in C++03
(`#82995 <https://github.com/llvm/llvm-project/issues/82995>`_)
``__has_cpp_attribute`` and parses attributes with arguments in C++03 (#GH82995)
- Clang now properly diagnoses missing 'default' template arguments on a variety
of templates. Previously we were diagnosing on any non-function template
instead of only on class, alias, and variable templates, as last updated by
CWG2032.
Fixes (`#83461 <https://github.com/llvm/llvm-project/issues/83461>`_)
CWG2032. Fixes (#GH83461)


Bug Fixes to AST Handling
Expand All @@ -321,6 +306,10 @@ Miscellaneous Bug Fixes
Miscellaneous Clang Crashes Fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Do not attempt to dump the layout of dependent types or invalid declarations
when ``-fdump-record-layouts-complete`` is passed.
Fixes (`#83684 <https://github.com/llvm/llvm-project/issues/83684>`_).

OpenACC Specific Changes
------------------------

Expand All @@ -346,6 +335,11 @@ Arm and AArch64 Support
improvements for most targets. We have not changed the default behavior for
ARMv6, but may revisit that decision in the future. Users can restore the old
behavior with -m[no-]unaligned-access.
- An alias identifier (rdma) has been added for targeting the AArch64
Architecture Extension which uses Rounding Doubling Multiply Accumulate
instructions (rdm). The identifier is available on the command line as
a feature modifier for -march and -mcpu as well as via target attributes
like ``target_version`` or ``target_clones``.

Android Support
^^^^^^^^^^^^^^^
Expand Down
21 changes: 17 additions & 4 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1320,10 +1320,23 @@ range of the argument.
**Parameters**
The checker models functions (and emits diagnostics) from the C standard by
default. The ``ModelPOSIX`` option enables modeling (and emit diagnostics) of
additional functions that are defined in the POSIX standard. This option is
disabled by default.
The ``ModelPOSIX`` option controls if functions from the POSIX standard are
recognized by the checker.
With ``ModelPOSIX=true``, many POSIX functions are modeled according to the
`POSIX standard`_. This includes ranges of parameters and possible return
values. Furthermore the behavior related to ``errno`` in the POSIX case is
often that ``errno`` is set only if a function call fails, and it becomes
undefined after a successful function call.
With ``ModelPOSIX=false``, this checker follows the C99 language standard and
only models the functions that are described there. It is possible that the
same functions are modeled differently in the two cases because differences in
the standards. The C standard specifies less aspects of the functions, for
example exact ``errno`` behavior is often unspecified (and not modeled by the
checker).
Default value of the option is ``true``.
.. _osx-checkers:
Expand Down
15 changes: 12 additions & 3 deletions clang/docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
# sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath("."))

# -- General configuration -----------------------------------------------------

Expand All @@ -27,16 +27,25 @@

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ["sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.graphviz"]
extensions = ["sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.graphviz", "ghlinks"]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]


import sphinx

if sphinx.version_info >= (3, 0):
# When building man pages, we do not use the markdown pages,
# So, we can continue without the myst_parser dependencies.
# Doing so reduces dependencies of some packaged llvm distributions.
try:
import myst_parser

extensions.append("myst_parser")
except ImportError:
if not tags.has("builder-man"):
raise


# The encoding of source files.
# source_encoding = 'utf-8-sig'
Expand Down
19 changes: 19 additions & 0 deletions clang/docs/ghlinks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

from sphinx.application import Sphinx
import re

__version__ = "1.0"


def subst_gh_links(app: Sphinx, docname, source):
regex = re.compile("#GH([0-9]+)")
out_pattern = r"`#\1 <https://github.com/llvm/llvm-project/issues/\1>`_"
result = source[0]
result = regex.sub(out_pattern, result)
source[0] = result


def setup(app: Sphinx):
app.connect("source-read", subst_gh_links)
return dict(version=__version__, parallel_read_safe=True, parallel_write_safe=True)
13 changes: 12 additions & 1 deletion clang/include/clang/APINotes/APINotesWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

//
// This file defines the \c APINotesWriter class that writes out source
// API notes data providing additional information about source code as
// a separate input, such as the non-nil/nilable annotations for
// method parameters.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_APINOTES_WRITER_H
#define LLVM_CLANG_APINOTES_WRITER_H

Expand All @@ -20,11 +26,16 @@ namespace clang {
class FileEntry;

namespace api_notes {

/// A class that writes API notes data to a binary representation that can be
/// read by the \c APINotesReader.
class APINotesWriter {
class Implementation;
std::unique_ptr<Implementation> Implementation;

public:
/// Create a new API notes writer with the given module name and
/// (optional) source file.
APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF);
~APINotesWriter();

Expand Down
16 changes: 7 additions & 9 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -4977,6 +4977,9 @@ def err_template_param_shadow : Error<
"declaration of %0 shadows template parameter">;
def ext_template_param_shadow : ExtWarn<
err_template_param_shadow.Summary>, InGroup<MicrosoftTemplateShadow>;
def ext_compat_template_param_shadow : ExtWarn<
err_template_param_shadow.Summary>, InGroup<
DiagGroup<"strict-primary-template-shadow">>, DefaultError;
def note_template_param_here : Note<"template parameter is declared here">;
def note_template_param_external : Note<
"template parameter from hidden source: %0">;
Expand Down Expand Up @@ -10266,15 +10269,10 @@ def err_block_on_vm : Error<
def err_sizeless_nonlocal : Error<
"non-local variable with sizeless type %0">;

def err_vec_builtin_non_vector_all : Error<
"all arguments to %0 must be vectors">;
def err_vec_builtin_incompatible_vector_all : Error<
"all arguments to %0 must have vectors of the same type">;

def err_vec_builtin_non_vector : Error<
"first two arguments to %0 must be vectors">;
"%select{first two|all}1 arguments to %0 must be vectors">;
def err_vec_builtin_incompatible_vector : Error<
"first two arguments to %0 must have the same type">;
"%select{first two|all}1 arguments to %0 must have the same type">;
def err_vsx_builtin_nonconstant_argument : Error<
"argument %0 to %1 must be a 2-bit unsigned literal (i.e. 0, 1, 2 or 3)">;

Expand Down Expand Up @@ -12217,8 +12215,8 @@ def err_acc_construct_appertainment
: Error<"OpenACC construct '%0' cannot be used here; it can only "
"be used in a statement context">;
def err_acc_branch_in_out_compute_construct
: Error<"invalid %select{branch|return}0 %select{out of|into}1 OpenACC "
"Compute Construct">;
: Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
"OpenACC Compute Construct">;
def note_acc_branch_into_compute_construct
: Note<"invalid branch into OpenACC Compute Construct">;
def note_acc_branch_out_of_compute_construct
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,6 @@ class Driver {
/// Target and driver mode components extracted from clang executable name.
ParsedClangName ClangNameParts;

/// TODO: Remove this in favor of Dir.
std::string InstalledDir;

/// The path to the compiler resource directory.
std::string ResourceDir;

Expand Down Expand Up @@ -429,8 +426,6 @@ class Driver {

/// Get the path to where the clang executable was installed.
const char *getInstalledDir() const {
if (!InstalledDir.empty())
return InstalledDir.c_str();
return Dir.c_str();
}

Expand Down Expand Up @@ -620,6 +615,16 @@ class Driver {
// FIXME: This should be in CompilationInfo.
std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;

/// Lookup the path to the Standard library module manifest.
///
/// \param C - The compilation.
/// \param TC - The tool chain for additional information on
/// directories to search.
//
// FIXME: This should be in CompilationInfo.
std::string GetStdModuleManifestPath(const Compilation &C,
const ToolChain &TC) const;

/// HandleAutocompletions - Handle --autocomplete by searching and printing
/// possible flags, descriptions, and its arguments.
void HandleAutocompletions(StringRef PassedFlags) const;
Expand Down
34 changes: 21 additions & 13 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,13 @@ multiclass BoolGOption<string flag_base, KeyPathAndMacro kpm,
Group<g_Group>;
}

multiclass BoolMOption<string flag_base, KeyPathAndMacro kpm,
Default default, FlagDef flag1, FlagDef flag2,
BothFlags both = BothFlags<[]>> {
defm NAME : BoolOption<"m", flag_base, kpm, default, flag1, flag2, both>,
Group<m_Group>;
}

// Works like BoolOption except without marshalling
multiclass BoolOptionWithoutMarshalling<string prefix = "", string spelling_base,
FlagDef flag1_base, FlagDef flag2_base,
Expand Down Expand Up @@ -4600,11 +4607,10 @@ def mretpoline : Flag<["-"], "mretpoline">, Group<m_Group>,
Visibility<[ClangOption, CLOption]>;
def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_Group>,
Visibility<[ClangOption, CLOption]>;
defm speculative_load_hardening : BoolOption<"m", "speculative-load-hardening",
defm speculative_load_hardening : BoolMOption<"speculative-load-hardening",
CodeGenOpts<"SpeculativeLoadHardening">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option]>,
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption]>>,
Group<m_Group>;
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption]>>;
def mlvi_hardening : Flag<["-"], "mlvi-hardening">, Group<m_Group>,
Visibility<[ClangOption, CLOption]>,
HelpText<"Enable all mitigations for Load Value Injection (LVI)">;
Expand Down Expand Up @@ -4821,13 +4827,13 @@ def mexec_model_EQ : Joined<["-"], "mexec-model=">, Group<m_wasm_Features_Driver
"explicitly terminated.">;
} // let Flags = [TargetSpecific]

defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",
defm amdgpu_ieee : BoolMOption<"amdgpu-ieee",
CodeGenOpts<"EmitIEEENaNCompliantInsts">, DefaultTrue,
PosFlag<SetTrue, [], [ClangOption], "Sets the IEEE bit in the expected default floating point "
" mode register. Floating point opcodes that support exception flag "
"gathering quiet and propagate signaling NaN inputs per IEEE 754-2008. "
"This option changes the ABI. (AMDGPU only)">,
NegFlag<SetFalse, [], [ClangOption, CC1Option]>>, Group<m_Group>;
NegFlag<SetFalse, [], [ClangOption, CC1Option]>>;

def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group<m_Group>,
HelpText<"Specify code object ABI version. Defaults to 5. (AMDGPU only)">,
Expand All @@ -4846,14 +4852,14 @@ defm wavefrontsize64 : SimpleMFlag<"wavefrontsize64",
"Specify wavefront size 64", "Specify wavefront size 32",
" mode (AMDGPU only)">;

defm unsafe_fp_atomics : BoolOption<"m", "unsafe-fp-atomics",
defm unsafe_fp_atomics : BoolMOption<"unsafe-fp-atomics",
TargetOpts<"AllowAMDGPUUnsafeFPAtomics">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Enable generation of unsafe floating point "
"atomic instructions. May generate more efficient code, but may not "
"respect rounding and denormal modes, and may give incorrect results "
"for certain memory destinations. (AMDGPU only)">,
NegFlag<SetFalse>>, Group<m_Group>;
NegFlag<SetFalse>>;

def faltivec : Flag<["-"], "faltivec">, Group<f_Group>;
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>;
Expand Down Expand Up @@ -4941,11 +4947,10 @@ def mrop_protect : Flag<["-"], "mrop-protect">,
def mprivileged : Flag<["-"], "mprivileged">,
Group<m_ppc_Features_Group>;

defm regnames : BoolOption<"m", "regnames",
defm regnames : BoolMOption<"regnames",
CodeGenOpts<"PPCUseFullRegisterNames">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use full register names when writing assembly output">,
NegFlag<SetFalse, [], [ClangOption], "Use only register numbers when writing assembly output">>,
Group<m_Group>;
NegFlag<SetFalse, [], [ClangOption], "Use only register numbers when writing assembly output">>;
} // let Flags = [TargetSpecific]
def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">,
Group<m_ppc_Features_Group>,
Expand Down Expand Up @@ -4987,10 +4992,10 @@ def mxcoff_build_id_EQ : Joined<["-"], "mxcoff-build-id=">, Group<Link_Group>, M
def mignore_xcoff_visibility : Flag<["-"], "mignore-xcoff-visibility">, Group<m_Group>,
HelpText<"Not emit the visibility attribute for asm in AIX OS or give all symbols 'unspecified' visibility in XCOFF object file">,
Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>;
defm backchain : BoolOption<"m", "backchain",
defm backchain : BoolMOption<"backchain",
CodeGenOpts<"Backchain">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Link stack frames through backchain on System Z">,
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>, Group<m_Group>;
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;

def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group<m_Group>;
def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group<m_Group>;
Expand Down Expand Up @@ -5359,6 +5364,9 @@ def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
HelpText<"Print the paths used for finding libraries and programs">,
Visibility<[ClangOption, CLOption]>;
def print_std_module_manifest_path : Flag<["-", "--"], "print-library-module-manifest-path">,
HelpText<"Print the path for the C++ Standard library module manifest">,
Visibility<[ClangOption, CLOption]>;
def print_targets : Flag<["-", "--"], "print-targets">,
HelpText<"Print the registered targets">,
Visibility<[ClangOption, CLOption]>;
Expand Down Expand Up @@ -6952,7 +6960,7 @@ def msmall_data_limit : Separate<["-"], "msmall-data-limit">,
def funwind_tables_EQ : Joined<["-"], "funwind-tables=">,
HelpText<"Generate unwinding tables for all functions">,
MarshallingInfoInt<CodeGenOpts<"UnwindTables">>;
defm constructor_aliases : BoolOption<"m", "constructor-aliases",
defm constructor_aliases : BoolMOption<"constructor-aliases",
CodeGenOpts<"CXXCtorDtorAliases">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ class CompilerInstance : public ModuleLoader {
// of the context or else not CompilerInstance specific.
bool ExecuteAction(FrontendAction &Act);

/// At the end of a compilation, print the number of warnings/errors.
void printDiagnosticStats();

/// Load the list of plugins requested in the \c FrontendOptions.
void LoadRequestedPlugins();

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ class CompilerInvocationBase {
/// @}
};

class CowCompilerInvocation;

/// Helper class for holding the data necessary to invoke the compiler.
///
/// This class is designed to represent an abstract "invocation" of the
Expand All @@ -220,6 +222,9 @@ class CompilerInvocation : public CompilerInvocationBase {
}
~CompilerInvocation() = default;

explicit CompilerInvocation(const CowCompilerInvocation &X);
CompilerInvocation &operator=(const CowCompilerInvocation &X);

/// Const getters.
/// @{
// Note: These need to be pulled in manually. Otherwise, they get hidden by
Expand Down
30 changes: 27 additions & 3 deletions clang/include/clang/InstallAPI/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/RecordVisitor.h"
#include "llvm/TextAPI/RecordsSlice.h"

namespace clang {
namespace installapi {
class FrontendRecordsSlice;

/// Struct used for generating validating InstallAPI.
/// The attributes captured represent all necessary information
Expand All @@ -37,7 +37,7 @@ struct InstallAPIContext {
HeaderType Type = HeaderType::Unknown;

/// Active TargetSlice for symbol record collection.
std::shared_ptr<llvm::MachO::RecordsSlice> Slice;
std::shared_ptr<FrontendRecordsSlice> Slice;

/// FileManager for all I/O operations.
FileManager *FM = nullptr;
Expand All @@ -50,6 +50,30 @@ struct InstallAPIContext {

/// What encoding to write output as.
llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5;

/// Populate entries of headers that should be included for TextAPI
/// generation.
void addKnownHeader(const HeaderFile &H);

/// Record visited files during frontend actions to determine whether to
/// include their declarations for TextAPI generation.
///
/// \param FE Header that is being parsed.
/// \param PP Preprocesser used for querying how header was imported.
/// \return Access level of header if it should be included for TextAPI
/// generation.
std::optional<HeaderType> findAndRecordFile(const FileEntry *FE,
const Preprocessor &PP);

private:
using HeaderMap = llvm::DenseMap<const FileEntry *, HeaderType>;

// Collection of parsed header files and their access level. If set to
// HeaderType::Unknown, they are not used for TextAPI generation.
HeaderMap KnownFiles;

// Collection of expected header includes and the access level for them.
llvm::DenseMap<StringRef, HeaderType> KnownIncludes;
};

} // namespace installapi
Expand Down
68 changes: 62 additions & 6 deletions clang/include/clang/InstallAPI/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_CLANG_INSTALLAPI_FRONTEND_H

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Availability.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/InstallAPI/Context.h"
Expand All @@ -24,23 +25,78 @@
namespace clang {
namespace installapi {

using SymbolFlags = llvm::MachO::SymbolFlags;
using RecordLinkage = llvm::MachO::RecordLinkage;
using GlobalRecord = llvm::MachO::GlobalRecord;
using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord;

// Represents a collection of frontend records for a library that are tied to a
// darwin target triple.
class FrontendRecordsSlice : public llvm::MachO::RecordsSlice {
public:
FrontendRecordsSlice(const llvm::Triple &T)
: llvm::MachO::RecordsSlice({T}) {}

/// Add non-ObjC global record with attributes from AST.
///
/// \param Name The name of symbol.
/// \param Linkage The linkage of symbol.
/// \param GV The kind of global.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param Flags The flags that describe attributes of the symbol.
/// \return The non-owning pointer to added record in slice.
GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
GlobalRecord::Kind GV,
const clang::AvailabilityInfo Avail, const Decl *D,
const HeaderType Access,
SymbolFlags Flags = SymbolFlags::None);

/// Add ObjC Class record with attributes from AST.
///
/// \param Name The name of class, not symbol.
/// \param Linkage The linkage of symbol.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param IsEHType Whether declaration has an exception attribute.
/// \return The non-owning pointer to added record in slice.
ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access,
bool IsEHType);

private:
/// Frontend information captured about records.
struct FrontendAttrs {
const AvailabilityInfo Avail;
const Decl *D;
const HeaderType Access;
};

/// Mapping of records stored in slice to their frontend attributes.
llvm::DenseMap<llvm::MachO::Record *, FrontendAttrs> FrontendRecords;
};

/// Create a buffer that contains all headers to scan
/// for global symbols with.
std::unique_ptr<llvm::MemoryBuffer>
createInputBuffer(const InstallAPIContext &Ctx);
std::unique_ptr<llvm::MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx);

class InstallAPIAction : public ASTFrontendAction {
public:
explicit InstallAPIAction(llvm::MachO::RecordsSlice &Records)
: Records(Records) {}
explicit InstallAPIAction(InstallAPIContext &Ctx) : Ctx(Ctx) {}

std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override {
return std::make_unique<InstallAPIVisitor>(CI.getASTContext(), Records);
return std::make_unique<InstallAPIVisitor>(
CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor());
}

private:
llvm::MachO::RecordsSlice &Records;
InstallAPIContext &Ctx;
};
} // namespace installapi
} // namespace clang
Expand Down
17 changes: 13 additions & 4 deletions clang/include/clang/InstallAPI/Visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/InstallAPI/Context.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TextAPI/RecordsSlice.h"

namespace clang {
namespace installapi {
Expand All @@ -27,20 +27,29 @@ namespace installapi {
class InstallAPIVisitor final : public ASTConsumer,
public RecursiveASTVisitor<InstallAPIVisitor> {
public:
InstallAPIVisitor(ASTContext &ASTCtx, llvm::MachO::RecordsSlice &Slice)
: Slice(Slice),
InstallAPIVisitor(ASTContext &ASTCtx, InstallAPIContext &Ctx,
SourceManager &SrcMgr, Preprocessor &PP)
: Ctx(Ctx), SrcMgr(SrcMgr), PP(PP),
MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
void HandleTranslationUnit(ASTContext &ASTCtx) override;

/// Collect global variables.
bool VisitVarDecl(const VarDecl *D);

/// Collect Objective-C Interface declarations.
/// Every Objective-C class has an interface declaration that lists all the
/// ivars, properties, and methods of the class.
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);

private:
std::string getMangledName(const NamedDecl *D) const;
std::string getBackendMangledName(llvm::Twine Name) const;
std::optional<HeaderType> getAccessForDecl(const NamedDecl *D) const;

llvm::MachO::RecordsSlice &Slice;
InstallAPIContext &Ctx;
SourceManager &SrcMgr;
Preprocessor &PP;
std::unique_ptr<clang::ItaniumMangleContext> MC;
StringRef Layout;
};
Expand Down
40 changes: 19 additions & 21 deletions clang/include/clang/Sema/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class Scope {
/// ScopeFlags - These are bitfields that are or'd together when creating a
/// scope, which defines the sorts of things the scope contains.
enum ScopeFlags {
// A bitfield value representing no scopes.
NoScope = 0,

/// This indicates that the scope corresponds to a function, which
/// means that labels are set here.
FnScope = 0x01,
Expand Down Expand Up @@ -203,6 +206,10 @@ class Scope {
/// other template parameter scopes as parents.
Scope *TemplateParamParent;

/// DeclScopeParent - This is a direct link to the immediately containing
/// DeclScope, i.e. scope which can contain declarations.
Scope *DeclParent;

/// DeclsInScope - This keeps track of all declarations in this scope. When
/// the declaration is added to the scope, it is set as the current
/// declaration for the identifier in the IdentifierTable. When the scope is
Expand Down Expand Up @@ -302,6 +309,9 @@ class Scope {
Scope *getTemplateParamParent() { return TemplateParamParent; }
const Scope *getTemplateParamParent() const { return TemplateParamParent; }

Scope *getDeclParent() { return DeclParent; }
const Scope *getDeclParent() const { return DeclParent; }

/// Returns the depth of this scope. The translation-unit has scope depth 0.
unsigned getDepth() const { return Depth; }

Expand Down Expand Up @@ -521,10 +531,17 @@ class Scope {
return getFlags() & Scope::OpenACCComputeConstructScope;
}

bool isInOpenACCComputeConstructScope() const {
/// Determine if this scope (or its parents) are a compute construct. If the
/// argument is provided, the search will stop at any of the specified scopes.
/// Otherwise, it will stop only at the normal 'no longer search' scopes.
bool isInOpenACCComputeConstructScope(ScopeFlags Flags = NoScope) const {
for (const Scope *S = this; S; S = S->getParent()) {
if (S->getFlags() & Scope::OpenACCComputeConstructScope)
if (S->isOpenACCComputeConstructScope())
return true;

if (S->getFlags() & Flags)
return false;

else if (S->getFlags() &
(Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
Scope::TemplateParamScope | Scope::FunctionPrototypeScope |
Expand All @@ -534,25 +551,6 @@ class Scope {
return false;
}

/// Determine if this scope (or its parents) are a compute construct inside of
/// the nearest 'switch' scope. This is needed to check whether we are inside
/// of a 'duffs' device, which is an illegal branch into a compute construct.
bool isInOpenACCComputeConstructBeforeSwitch() const {
for (const Scope *S = this; S; S = S->getParent()) {
if (S->getFlags() & Scope::OpenACCComputeConstructScope)
return true;
if (S->getFlags() & Scope::SwitchScope)
return false;

if (S->getFlags() &
(Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
Scope::TemplateParamScope | Scope::FunctionPrototypeScope |
Scope::AtCatchScope | Scope::ObjCMethodScope))
return false;
}
return false;
}

/// Determine whether this scope is a while/do/for statement, which can have
/// continue statements embedded into it.
bool isContinueScope() const {
Expand Down
16 changes: 15 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8386,7 +8386,21 @@ class Sema final {
TemplateSpecializationKind TSK,
bool Complain = true);

void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
/// that the template parameter 'PrevDecl' is being shadowed by a new
/// declaration at location Loc. Returns true to indicate that this is
/// an error, and false otherwise.
///
/// \param Loc The location of the declaration that shadows a template
/// parameter.
///
/// \param PrevDecl The template parameter that the declaration shadows.
///
/// \param SupportedForCompatibility Whether to issue the diagnostic as
/// a warning for compatibility with older versions of clang.
/// Ignored when MSVC compatibility is enabled.
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
bool SupportedForCompatibility = false);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);

NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
"ModelPOSIX",
"If set to true, the checker models additional functions "
"from the POSIX standard.",
"false",
"true",
InAlpha>
]>,
WeakDependencies<[CallAndMessageChecker, NonNullParamChecker]>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,48 @@ class IdentifierInfo;

namespace clang {
namespace ento {

enum CallDescriptionFlags : unsigned {
CDF_None = 0,

/// Describes a C standard function that is sometimes implemented as a macro
/// that expands to a compiler builtin with some __builtin prefix.
/// The builtin may as well have a few extra arguments on top of the requested
/// number of arguments.
CDF_MaybeBuiltin = 1 << 0,
};

/// This class represents a description of a function call using the number of
/// arguments and the name of the function.
/// A `CallDescription` is a pattern that can be used to _match_ calls
/// based on the qualified name and the argument/parameter counts.
class CallDescription {
public:
enum class Mode {
/// Match calls to functions from the C standard library. On some platforms
/// some functions may be implemented as macros that expand to calls to
/// built-in variants of the given functions, so in this mode we use some
/// heuristics to recognize these implementation-defined variants:
/// - We also accept calls where the name is derived from the specified
/// name by adding "__builtin" or similar prefixes/suffixes.
/// - We also accept calls where the number of arguments or parameters is
/// greater than the specified value.
/// For the exact heuristics, see CheckerContext::isCLibraryFunction().
/// Note that functions whose declaration context is not a TU (e.g.
/// methods, functions in namespaces) are not accepted as C library
/// functions.
/// FIXME: If I understand it correctly, this discards calls where C++ code
/// refers a C library function through the namespace `std::` via headers
/// like <cstdlib>.
CLibrary,

/// Matches "simple" functions that are not methods. (Static methods are
/// methods.)
SimpleFunc,

/// Matches a C++ method (may be static, may be virtual, may be an
/// overloaded operator, a constructor or a destructor).
CXXMethod,

/// Match any CallEvent that is not an ObjCMethodCall.
/// FIXME: Previously this was the default behavior of CallDescription, but
/// its use should be replaced by a more specific mode almost everywhere.
Unspecified,

/// FIXME: Add support for ObjCMethodCall events (I'm not adding it because
/// I'm not familiar with Objective-C). Note that currently an early return
/// in `bool matches(const CallEvent &Call) const;` discards all
/// Objective-C method calls.
};

private:
friend class CallEvent;
using MaybeCount = std::optional<unsigned>;

Expand All @@ -50,20 +78,26 @@ class CallDescription {
std::vector<std::string> QualifiedName;
MaybeCount RequiredArgs;
MaybeCount RequiredParams;
int Flags;
Mode MatchAs;

public:
/// Constructs a CallDescription object.
///
/// @param MatchAs Specifies the kind of the call that should be matched.
///
/// @param QualifiedName The list of the name qualifiers of the function that
/// will be matched. The user is allowed to skip any of the qualifiers.
/// For example, {"std", "basic_string", "c_str"} would match both
/// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str().
///
/// @param RequiredArgs The number of arguments that is expected to match a
/// call. Omit this parameter to match every occurrence of call with a given
/// name regardless the number of arguments.
CallDescription(CallDescriptionFlags Flags, ArrayRef<StringRef> QualifiedName,
/// @param RequiredArgs The expected number of arguments that are passed to
/// the function. Omit this parameter (or pass std::nullopt) to match every
/// occurrence without checking the argument count in the call.
///
/// @param RequiredParams The expected number of parameters in the function
/// definition that is called. Omit this parameter to match every occurrence
/// without checking the parameter count in the definition.
CallDescription(Mode MatchAs, ArrayRef<StringRef> QualifiedName,
MaybeCount RequiredArgs = std::nullopt,
MaybeCount RequiredParams = std::nullopt);

Expand Down Expand Up @@ -222,6 +256,10 @@ template <typename T> class CallDescriptionMap {
}
};

/// Enumerators of this enum class are used to construct CallDescription
/// objects; in that context the fully qualified name is needlessly verbose.
using CDM = CallDescription::Mode;

/// An immutable set of CallDescriptions.
/// Checkers can efficiently decide if a given CallEvent matches any
/// CallDescription in the set.
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

//
// This file implements the \c APINotesReader class that reads source
// API notes data providing additional information about source code as
// a separate input, such as the non-nil/nilable annotations for
// method parameters.
//
//===----------------------------------------------------------------------===//
#include "clang/APINotes/APINotesReader.h"
#include "APINotesFormat.h"
#include "llvm/ADT/Hashing.h"
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5042,7 +5042,13 @@ void RecordDecl::completeDefinition() {

// Layouts are dumped when computed, so if we are dumping for all complete
// types, we need to force usage to get types that wouldn't be used elsewhere.
if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
//
// If the type is dependent, then we can't compute its layout because there
// is no way for us to know the size or alignment of a dependent type. Also
// ignore declarations marked as invalid since 'getASTRecordLayout()' asserts
// on that.
if (Ctx.getLangOpts().DumpRecordLayoutsComplete && !isDependentType() &&
!isInvalidDecl())
(void)Ctx.getASTRecordLayout(this);
}

Expand Down
13 changes: 7 additions & 6 deletions clang/lib/AST/Interp/ByteCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
this->LambdaCaptures[Cap.first] = {
Offset, Cap.second->getType()->isReferenceType()};
}
if (LTC)
this->LambdaThisCapture = R->getField(LTC)->Offset;
if (LTC) {
QualType CaptureType = R->getField(LTC)->Decl->getType();
this->LambdaThisCapture = {R->getField(LTC)->Offset,
CaptureType->isReferenceType() ||
CaptureType->isPointerType()};
}
}
}

Expand Down Expand Up @@ -298,10 +302,7 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &S
if (SI)
SrcMap.emplace_back(Code.size(), SI);

// The initializer list forces the expression to be evaluated
// for each argument in the variadic template, in order.
(void)std::initializer_list<int>{(emit(P, Code, Args, Success), 0)...};

(..., emit(P, Code, Args, Success));
return Success;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class ByteCodeEmitter {
/// Lambda captures.
llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures;
/// Offset of the This parameter in a lambda record.
unsigned LambdaThisCapture = 0;
ParamOffset LambdaThisCapture{0, false};
/// Local descriptors.
llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;

Expand Down
12 changes: 10 additions & 2 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2663,6 +2663,11 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
if (P.getGlobal(VD))
return true;

// Ignore external declarations. We will instead emit a dummy
// pointer when we see a DeclRefExpr for them.
if (VD->hasExternalStorage())
return true;

std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);

if (!GlobalIndex)
Expand Down Expand Up @@ -2934,8 +2939,11 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
if (DiscardResult)
return true;

if (this->LambdaThisCapture > 0)
return this->emitGetThisFieldPtr(this->LambdaThisCapture, E);
if (this->LambdaThisCapture.Offset > 0) {
if (this->LambdaThisCapture.IsPtr)
return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);
return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);
}

return this->emitThis(E);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/EvalEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class EvalEmitter : public SourceMapper {
/// Lambda captures.
llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures;
/// Offset of the This parameter in a lambda record.
unsigned LambdaThisCapture = 0;
ParamOffset LambdaThisCapture{0, false};
/// Local descriptors.
llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,8 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
if (Ptr.isUnknownSizeArray())
return false;
if (!CheckInit(S, OpPC, Ptr))
return false;
Ptr.initialize();
Expand All @@ -1460,6 +1462,8 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
if (Ptr.isUnknownSizeArray())
return false;
if (!CheckInit(S, OpPC, Ptr))
return false;
Ptr.initialize();
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
return false;

if (A.isDummy() || B.isDummy())
return false;

assert(A.getFieldDesc()->isPrimitiveArray());
assert(B.getFieldDesc()->isPrimitiveArray());

Expand Down Expand Up @@ -460,9 +463,6 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {

Func->getDecl()->dump();

PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.popcount(), Call->getType());
Expand Down Expand Up @@ -1207,6 +1207,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
break;

default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
<< S.Current->getRange(OpPC);

return false;
}

Expand All @@ -1230,7 +1234,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return false;
RecordDecl *RD = RT->getDecl();
const RecordDecl *RD = RT->getDecl();
if (RD->isInvalidDecl())
return false;
const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
Expand Down
29 changes: 8 additions & 21 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17091,37 +17091,24 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
}
return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
}
// Rotate and insert under mask operation.
// __rldimi(rs, is, shift, mask)
// (rotl64(rs, shift) & mask) | (is & ~mask)
// __rlwimi(rs, is, shift, mask)
// (rotl(rs, shift) & mask) | (is & ~mask)
case PPC::BI__builtin_ppc_rldimi:
case PPC::BI__builtin_ppc_rlwimi: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
Value *Op3 = EmitScalarExpr(E->getArg(3));
llvm::Type *Ty = Op0->getType();
Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
if (BuiltinID == PPC::BI__builtin_ppc_rldimi)
Op2 = Builder.CreateZExt(Op2, Int64Ty);
Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});
Value *X = Builder.CreateAnd(Shift, Op3);
Value *Y = Builder.CreateAnd(Op1, Builder.CreateNot(Op3));
return Builder.CreateOr(X, Y);
}
// Rotate and insert under mask operation.
// __rlwnm(rs, shift, mask)
// rotl(rs, shift) & mask
return Builder.CreateCall(
CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi
? Intrinsic::ppc_rldimi
: Intrinsic::ppc_rlwimi),
{Op0, Op1, Op2, Op3});
}
case PPC::BI__builtin_ppc_rlwnm: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
llvm::Type *Ty = Op0->getType();
Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op1});
return Builder.CreateAnd(Shift, Op2);
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_rlwnm),
{Op0, Op1, Op2});
}
case PPC::BI__builtin_ppc_poppar4:
case PPC::BI__builtin_ppc_poppar8: {
Expand Down
51 changes: 47 additions & 4 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,10 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,

Name = std::string(llvm::sys::path::filename(ClangExecutable));
Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));
InstalledDir = Dir; // Provide a sensible default installed dir.

if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {
// Prepend InstalledDir if SysRoot is relative
SmallString<128> P(InstalledDir);
SmallString<128> P(Dir);
llvm::sys::path::append(P, SysRoot);
SysRoot = std::string(P);
}
Expand Down Expand Up @@ -1337,7 +1336,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (const Arg *A = Args.getLastArg(options::OPT_target))
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Dir = InstalledDir = A->getValue();
Dir = Dir = A->getValue();
for (const Arg *A : Args.filtered(options::OPT_B)) {
A->claim();
PrefixDirs.push_back(A->getValue(0));
Expand Down Expand Up @@ -2000,7 +1999,7 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
OS << '\n';

// Print out the install directory.
OS << "InstalledDir: " << InstalledDir << '\n';
OS << "InstalledDir: " << Dir << '\n';

// If configuration files were used, print their paths.
for (auto ConfigFile : ConfigFiles)
Expand Down Expand Up @@ -2197,6 +2196,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}

if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) {
llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain())
<< '\n';
return false;
}

if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
if (std::optional<std::string> RuntimePath = TC.getRuntimePath())
llvm::outs() << *RuntimePath << '\n';
Expand Down Expand Up @@ -6169,6 +6174,44 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
return std::string(Name);
}

std::string Driver::GetStdModuleManifestPath(const Compilation &C,
const ToolChain &TC) const {
std::string error = "<NOT PRESENT>";

switch (TC.GetCXXStdlibType(C.getArgs())) {
case ToolChain::CST_Libcxx: {
std::string lib = GetFilePath("libc++.so", TC);

// Note when there are multiple flavours of libc++ the module json needs to
// look at the command-line arguments for the proper json.
// These flavours do not exist at the moment, but there are plans to
// provide a variant that is built with sanitizer instrumentation enabled.

// For example
// StringRef modules = [&] {
// const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());
// if (Sanitize.needsAsanRt())
// return "modules-asan.json";
// return "modules.json";
// }();

SmallString<128> path(lib.begin(), lib.end());
llvm::sys::path::remove_filename(path);
llvm::sys::path::append(path, "modules.json");
if (TC.getVFS().exists(path))
return static_cast<std::string>(path);

return error;
}

case ToolChain::CST_Libstdcxx:
// libstdc++ does not provide Standard library modules yet.
return error;
}

return error;
}

std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
SmallString<128> Path;
std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,7 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);

ParseInlineAsmUsingAsmParser = Args.hasFlag(
options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
}

// Try to find relative to the compiler binary.
const char *InstallDir = D.getInstalledDir();
StringRef InstallDir = D.Dir;

// Check both a normal Unix prefix position of the clang binary, as well as
// the Windows-esque layout the ROCm packages use with the host architecture
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,14 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
MtuneLowerCase = std::string(llvm::sys::getHostCPUName());

// 'cyclone' and later have zero-cycle register moves and zeroing.
if (MtuneLowerCase == "cyclone" ||
StringRef(MtuneLowerCase).starts_with("apple")) {
Features.push_back("+zcm");
Features.push_back("+zcz");
}

return true;
}

Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ static bool findRISCVMultilibs(const Driver &D,
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);

findMultilibs(D, Triple, Args);
SmallString<128> SysRoot(computeSysRoot());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
if ((getToolChain().getTriple().isNVPTX() ||
getToolChain().getTriple().isAMDGCN()) &&
C.getActiveOffloadKinds() == Action::OFK_None) {
SmallString<128> P(llvm::sys::path::parent_path(D.InstalledDir));
SmallString<128> P(llvm::sys::path::parent_path(D.Dir));
llvm::sys::path::append(P, "include");
llvm::sys::path::append(P, getToolChain().getTripleString());
CmdArgs.push_back("-internal-isystem");
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2767,10 +2767,6 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
const ToolChain &HostTC) {
SmallVector<StringRef, 8> LibraryPaths;

// Check all of the standard library search paths used by the compiler.
for (const auto &LibPath : HostTC.getFilePaths())
LibraryPaths.emplace_back(LibPath);

// Add user defined library paths from LIBRARY_PATH.
std::optional<std::string> LibPath =
llvm::sys::Process::GetEnv("LIBRARY_PATH");
Expand All @@ -2782,6 +2778,10 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
LibraryPaths.emplace_back(Path.trim());
}

// Check all of the standard library search paths used by the compiler.
for (const auto &LibPath : HostTC.getFilePaths())
LibraryPaths.emplace_back(LibPath);

OptSpecifier LibomptargetBCPathOpt =
Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
: options::OPT_libomptarget_nvptx_bc_path_EQ;
Expand Down
36 changes: 7 additions & 29 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,9 +643,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,

// It seems that the 'e' option is completely ignored for dynamic executables
// (the default), and with static executables, the last one wins, as expected.
Args.addAllArgs(CmdArgs,
{options::OPT_d_Flag, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_u_Group, options::OPT_r});
Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_u_Group});

// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
// members of static archive libraries which implement Objective-C classes or
Expand Down Expand Up @@ -926,9 +925,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);
}

/// Darwin - Darwin tool chain for i386 and x86_64.
Expand Down Expand Up @@ -2517,25 +2514,19 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
// On Darwin, libc++ can be installed in one of the following places:
// 1. Alongside the compiler in <install>/include/c++/v1
// 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
// 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
// 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
// 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
//
// The precedence of paths is as listed above, i.e. we take the first path
// that exists. Note that we never include libc++ twice -- we take the first
// path that exists and don't send the other paths to CC1 (otherwise
// include_next could break).
//
// Also note that in most cases, (1) and (2) are exactly the same path.
// Those two paths will differ only when the `clang` program being run
// is actually a symlink to the real executable.

// Check for (1)
// Get from '<install>/bin' to '<install>/include/c++/v1'.
// Note that InstallBin can be relative, so we use '..' instead of
// parent_path.
llvm::SmallString<128> InstallBin =
llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin
llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin
llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
if (getVFS().exists(InstallBin)) {
addSystemInclude(DriverArgs, CC1Args, InstallBin);
Expand All @@ -2545,20 +2536,7 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
<< "\"\n";
}

// (2) Check for the folder where the executable is located, if different.
if (getDriver().getInstalledDir() != getDriver().Dir) {
InstallBin = llvm::StringRef(getDriver().Dir);
llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
if (getVFS().exists(InstallBin)) {
addSystemInclude(DriverArgs, CC1Args, InstallBin);
return;
} else if (DriverArgs.hasArg(options::OPT_v)) {
llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
<< "\"\n";
}
}

// Otherwise, check for (3)
// Otherwise, check for (2)
llvm::SmallString<128> SysrootUsr = Sysroot;
llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
if (getVFS().exists(SysrootUsr)) {
Expand Down
7 changes: 2 additions & 5 deletions clang/lib/Driver/ToolChains/DragonFly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}

Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_s, options::OPT_t, options::OPT_r});
options::OPT_s, options::OPT_t});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);

AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
Expand Down Expand Up @@ -205,11 +205,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {

// Path mangling to find libexec
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);

getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/FreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,

Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
options::OPT_t, options::OPT_r});
Args.addAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_s, options::OPT_t});

if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Driver/ToolChains/Fuchsia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,7 @@ void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != D.Dir)
getProgramPaths().push_back(D.Dir);
getProgramPaths().push_back(getDriver().Dir);

if (!D.SysRoot.empty()) {
SmallString<128> P(D.SysRoot);
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2285,7 +2285,7 @@ void Generic_GCC::GCCInstallationDetector::init(
}

// Then look for gcc installed alongside clang.
Prefixes.push_back(D.InstalledDir + "/..");
Prefixes.push_back(D.Dir + "/..");

// Next, look for prefix(es) that correspond to distribution-supplied gcc
// installations.
Expand Down Expand Up @@ -3054,9 +3054,7 @@ Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), GCCInstallation(D),
CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);
}

Generic_GCC::~Generic_GCC() {}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Haiku.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}

Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_s, options::OPT_t, options::OPT_r});
options::OPT_s, options::OPT_t});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);

if (D.isUsingLTO()) {
Expand Down
15 changes: 6 additions & 9 deletions clang/lib/Driver/ToolChains/Hexagon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
const std::string MCpuSuffix = "/" + CpuVer.str();
const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
const std::string RootDir =
HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";
const std::string StartSubDir =
"hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);

Expand Down Expand Up @@ -569,8 +569,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
std::back_inserter(RootDirs));

std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
if (!llvm::is_contained(RootDirs, TargetDir))
RootDirs.push_back(TargetDir);

Expand All @@ -597,8 +596,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: Linux(D, Triple, Args) {
const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);

// Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
// program paths
Expand Down Expand Up @@ -728,8 +726,7 @@ void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,

if (HasSysRoot)
return;
std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
}

Expand All @@ -744,7 +741,7 @@ void HexagonToolChain::addLibCxxIncludePaths(
addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
CC1Args);
else {
std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
DriverArgs, CC1Args);
}
Expand All @@ -753,7 +750,7 @@ void HexagonToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
DriverArgs, CC1Args);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ std::string Linux::computeSysRoot() const {
if (getTriple().isAndroid()) {
// Android toolchains typically include a sysroot at ../sysroot relative to
// the clang binary.
const StringRef ClangDir = getDriver().getInstalledDir();
const StringRef ClangDir = getDriver().Dir;
std::string AndroidSysRootPath = (ClangDir + "/../sysroot").str();
if (getVFS().exists(AndroidSysRootPath))
return AndroidSysRootPath;
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,9 +423,7 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getProgramPaths().push_back(getDriver().Dir);

std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
Expand Down
9 changes: 4 additions & 5 deletions clang/lib/Driver/ToolChains/MinGW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
Subdirs.back() += "-w64-mingw32";
Subdirs.emplace_back(T.getArchName());
Subdirs.back() += "-w64-mingw32ucrt";
StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
StringRef ClangRoot = llvm::sys::path::parent_path(D.Dir);
StringRef Sep = llvm::sys::path::get_separator();
for (StringRef CandidateSubdir : Subdirs) {
if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
Expand All @@ -487,10 +487,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
getProgramPaths().push_back(getDriver().Dir);

std::string InstallBase =
std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir()));
std::string(llvm::sys::path::parent_path(getDriver().Dir));
// The sequence for detecting a sysroot here should be kept in sync with
// the testTriple function below.
llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
Expand Down Expand Up @@ -796,8 +796,7 @@ static bool testTriple(const Driver &D, const llvm::Triple &Triple,
if (D.SysRoot.size())
return true;
llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
std::string InstallBase =
std::string(llvm::sys::path::parent_path(D.getInstalledDir()));
std::string InstallBase = std::string(llvm::sys::path::parent_path(D.Dir));
if (llvm::ErrorOr<std::string> TargetSubdir =
findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
return true;
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Driver/ToolChains/MipsLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ void MipsLLVMToolChain::AddClangSystemIncludeArgs(
const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
for (const auto &Path : Callback(SelectedMultilibs.back()))
addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
D.getInstalledDir() + Path);
addExternCSystemIncludeIfExists(DriverArgs, CC1Args, D.Dir + Path);
}
}

Expand All @@ -70,7 +69,7 @@ std::string MipsLLVMToolChain::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot + SelectedMultilibs.back().osSuffix();

const std::string InstalledDir(getDriver().getInstalledDir());
const std::string InstalledDir(getDriver().Dir);
std::string SysRootPath =
InstalledDir + "/../sysroot" + SelectedMultilibs.back().osSuffix();
if (llvm::sys::fs::exists(SysRootPath))
Expand All @@ -97,7 +96,7 @@ void MipsLLVMToolChain::addLibCxxIncludePaths(
llvm::opt::ArgStringList &CC1Args) const {
if (const auto &Callback = Multilibs.includeDirsCallback()) {
for (std::string Path : Callback(SelectedMultilibs.back())) {
Path = getDriver().getInstalledDir() + Path + "/c++/v1";
Path = getDriver().Dir + Path + "/c++/v1";
if (llvm::sys::fs::exists(Path)) {
addSystemInclude(DriverArgs, CC1Args, Path);
return;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/NetBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}

Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_s, options::OPT_t, options::OPT_r});
options::OPT_s, options::OPT_t});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);

bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/OHOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ std::string OHOS::computeSysRoot() const {
std::string SysRoot =
!getDriver().SysRoot.empty()
? getDriver().SysRoot
: makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"});
: makePath({getDriver().Dir, "..", "..", "sysroot"});
if (!llvm::sys::fs::exists(SysRoot))
return std::string();

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/OpenBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,

Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
options::OPT_t, options::OPT_r});
Args.addAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_s, options::OPT_t});

if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,8 @@ void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--lto=full");
}

Args.addAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_s,
options::OPT_t, options::OPT_r});
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_s, options::OPT_t});

if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Driver/ToolChains/Solaris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,

ToolChain.AddFilePathLibArgs(Args, CmdArgs);

Args.addAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_r});
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group});

bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,

assert(Triple.isArch32Bit() != Triple.isArch64Bit());

getProgramPaths().push_back(getDriver().getInstalledDir());
getProgramPaths().push_back(getDriver().Dir);

auto SysRoot = getDriver().SysRoot;
if (getTriple().getOS() == llvm::Triple::UnknownOS) {
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Driver/ToolChains/ZOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,7 @@ void ZOS::AddClangCXXStdlibIncludeArgs(
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
// <install>/bin/../include/c++/v1
llvm::SmallString<128> InstallBin =
llvm::StringRef(getDriver().getInstalledDir());
llvm::SmallString<128> InstallBin(getDriver().Dir);
llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args);
break;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,8 @@ struct FormatToken {

/// Returns whether the token is the left square bracket of a C++
/// structured binding declaration.
bool isCppStructuredBinding(const FormatStyle &Style) const {
if (!Style.isCpp() || isNot(tok::l_square))
bool isCppStructuredBinding(bool IsCpp) const {
if (!IsCpp || isNot(tok::l_square))
return false;
const FormatToken *T = this;
do {
Expand Down
Loading