78 changes: 70 additions & 8 deletions clang-tools-extra/clangd/InlayHints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
#include "Config.h"
#include "HeuristicResolver.h"
#include "ParsedAST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
Expand All @@ -23,15 +25,22 @@
#include "clang/AST/Type.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <iterator>
#include <optional>
#include <string>

Expand Down Expand Up @@ -372,6 +381,23 @@ maybeDropCxxExplicitObjectParameters(ArrayRef<const ParmVarDecl *> Params) {
return Params;
}

template <typename R>
std::string joinAndTruncate(const R &Range, size_t MaxLength) {
std::string Out;
llvm::raw_string_ostream OS(Out);
llvm::ListSeparator Sep(", ");
for (auto &&Element : Range) {
OS << Sep;
if (Out.size() + Element.size() >= MaxLength) {
OS << "...";
break;
}
OS << Element;
}
OS.flush();
return Out;
}

struct Callee {
// Only one of Decl or Loc is set.
// Loc is for calls through function pointers.
Expand Down Expand Up @@ -422,7 +448,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
Callee.Decl = E->getConstructor();
if (!Callee.Decl)
return true;
processCall(Callee, {E->getArgs(), E->getNumArgs()});
processCall(Callee, E->getParenOrBraceRange().getEnd(),
{E->getArgs(), E->getNumArgs()});
return true;
}

Expand Down Expand Up @@ -495,7 +522,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl))
if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter())
Args = Args.drop_front(1);
processCall(Callee, Args);
processCall(Callee, E->getRParenLoc(), Args);
return true;
}

Expand Down Expand Up @@ -709,10 +736,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
private:
using NameVec = SmallVector<StringRef, 8>;

void processCall(Callee Callee, llvm::ArrayRef<const Expr *> Args) {
void processCall(Callee Callee, SourceLocation RParenOrBraceLoc,
llvm::ArrayRef<const Expr *> Args) {
assert(Callee.Decl || Callee.Loc);

if (!Cfg.InlayHints.Parameters || Args.size() == 0)
if ((!Cfg.InlayHints.Parameters && !Cfg.InlayHints.DefaultArguments) ||
Args.size() == 0)
return;

// The parameter name of a move or copy constructor is not very interesting.
Expand All @@ -721,6 +750,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
if (Ctor->isCopyOrMoveConstructor())
return;

SmallVector<std::string> FormattedDefaultArgs;
bool HasNonDefaultArgs = false;

ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
// Resolve parameter packs to their forwarded parameter
SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
Expand Down Expand Up @@ -752,15 +784,44 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
}

StringRef Name = ParameterNames[I];
bool NameHint = shouldHintName(Args[I], Name);
bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]);

if (NameHint || ReferenceHint) {
const bool NameHint =
shouldHintName(Args[I], Name) && Cfg.InlayHints.Parameters;
const bool ReferenceHint =
shouldHintReference(Params[I], ForwardedParams[I]) &&
Cfg.InlayHints.Parameters;

const bool IsDefault = isa<CXXDefaultArgExpr>(Args[I]);
HasNonDefaultArgs |= !IsDefault;
if (IsDefault) {
if (Cfg.InlayHints.DefaultArguments) {
const auto SourceText = Lexer::getSourceText(
CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()),
AST.getSourceManager(), AST.getLangOpts());
const auto Abbrev =
(SourceText.size() > Cfg.InlayHints.TypeNameLimit ||
SourceText.contains("\n"))
? "..."
: SourceText;
if (NameHint)
FormattedDefaultArgs.emplace_back(
llvm::formatv("{0}: {1}", Name, Abbrev));
else
FormattedDefaultArgs.emplace_back(llvm::formatv("{0}", Abbrev));
}
} else if (NameHint || ReferenceHint) {
addInlayHint(Args[I]->getSourceRange(), HintSide::Left,
InlayHintKind::Parameter, ReferenceHint ? "&" : "",
NameHint ? Name : "", ": ");
}
}

if (!FormattedDefaultArgs.empty()) {
std::string Hint =
joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit);
addInlayHint(SourceRange{RParenOrBraceLoc}, HintSide::Left,
InlayHintKind::DefaultArgument,
HasNonDefaultArgs ? ", " : "", Hint, "");
}
}

static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) {
Expand Down Expand Up @@ -968,6 +1029,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
CHECK_KIND(Type, DeducedTypes);
CHECK_KIND(Designator, Designators);
CHECK_KIND(BlockEnd, BlockEnd);
CHECK_KIND(DefaultArgument, DefaultArguments);
#undef CHECK_KIND
}

Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clangd/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,7 @@ llvm::json::Value toJSON(const InlayHintKind &Kind) {
return 2;
case InlayHintKind::Designator:
case InlayHintKind::BlockEnd:
case InlayHintKind::DefaultArgument:
// This is an extension, don't serialize.
return nullptr;
}
Expand Down Expand Up @@ -1517,6 +1518,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) {
return "designator";
case InlayHintKind::BlockEnd:
return "block-end";
case InlayHintKind::DefaultArgument:
return "default-argument";
}
llvm_unreachable("Unknown clang.clangd.InlayHintKind");
};
Expand Down
9 changes: 9 additions & 0 deletions clang-tools-extra/clangd/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,15 @@ enum class InlayHintKind {
/// This is a clangd extension.
BlockEnd = 4,

/// An inlay hint that is for a default argument.
///
/// An example of a parameter hint for a default argument:
/// void foo(bool A = true);
/// foo(^);
/// Adds an inlay hint "A: true".
/// This is a clangd extension.
DefaultArgument = 6,

/// Other ideas for hints that are not currently implemented:
///
/// * Chaining hints, showing the types of intermediate expressions
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/clangd/URI.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,8 @@ typedef llvm::Registry<URIScheme> URISchemeRegistry;
} // namespace clangd
} // namespace clang

namespace llvm {
extern template class Registry<clang::clangd::URIScheme>;
} // namespace llvm

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H
4 changes: 4 additions & 0 deletions clang-tools-extra/clangd/refactor/Tweak.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,8 @@ prepareTweak(StringRef ID, const Tweak::Selection &S,
} // namespace clangd
} // namespace clang

namespace llvm {
extern template class Registry<clang::clangd::Tweak>;
} // namespace llvm

#endif
73 changes: 73 additions & 0 deletions clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
#include "support/Context.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace clang {
Expand Down Expand Up @@ -81,6 +84,7 @@ Config noHintsConfig() {
C.InlayHints.DeducedTypes = false;
C.InlayHints.Designators = false;
C.InlayHints.BlockEnd = false;
C.InlayHints.DefaultArguments = false;
return C;
}

Expand Down Expand Up @@ -1465,6 +1469,75 @@ TEST(TypeHints, DefaultTemplateArgs) {
ExpectedHint{": A<float>", "binding"});
}

TEST(DefaultArguments, Smoke) {
Config Cfg;
Cfg.InlayHints.Parameters =
true; // To test interplay of parameters and default parameters
Cfg.InlayHints.DeducedTypes = false;
Cfg.InlayHints.Designators = false;
Cfg.InlayHints.BlockEnd = false;

Cfg.InlayHints.DefaultArguments = true;
WithContextValue WithCfg(Config::Key, std::move(Cfg));

const auto *Code = R"cpp(
int foo(int A = 4) { return A; }
int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; }
int A = bar($explicit[[2]]$default2[[)]];
void baz(int = 5) { if (false) baz($unnamed[[)]]; };
)cpp";

assertHints(InlayHintKind::DefaultArgument, Code,
ExpectedHint{"A: 4", "default1", Left},
ExpectedHint{", B: 1, C: foo()", "default2", Left},
ExpectedHint{"5", "unnamed", Left});

assertHints(InlayHintKind::Parameter, Code,
ExpectedHint{"A: ", "explicit", Left});
}

TEST(DefaultArguments, WithoutParameterNames) {
Config Cfg;
Cfg.InlayHints.Parameters = false; // To test just default args this time
Cfg.InlayHints.DeducedTypes = false;
Cfg.InlayHints.Designators = false;
Cfg.InlayHints.BlockEnd = false;

Cfg.InlayHints.DefaultArguments = true;
WithContextValue WithCfg(Config::Key, std::move(Cfg));

const auto *Code = R"cpp(
struct Baz {
Baz(float a = 3 //
+ 2);
};
struct Foo {
Foo(int, Baz baz = //
Baz{$abbreviated[[}]]
//
) {}
};
int main() {
Foo foo1(1$paren[[)]];
Foo foo2{2$brace1[[}]];
Foo foo3 = {3$brace2[[}]];
auto foo4 = Foo{4$brace3[[}]];
}
)cpp";

assertHints(InlayHintKind::DefaultArgument, Code,
ExpectedHint{"...", "abbreviated", Left},
ExpectedHint{", Baz{}", "paren", Left},
ExpectedHint{", Baz{}", "brace1", Left},
ExpectedHint{", Baz{}", "brace2", Left},
ExpectedHint{", Baz{}", "brace3", Left});

assertHints(InlayHintKind::Parameter, Code);
}

TEST(TypeHints, Deduplication) {
assertTypeHints(R"cpp(
template <typename T>
Expand Down
2 changes: 2 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Improvements to clangd
Inlay hints
^^^^^^^^^^^

- Added `DefaultArguments` Inlay Hints option.

Diagnostics
^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ For example:
}
}
Exception: accessor methods
```````````````````````````

The check assumes *accessor* methods of a class are stable, with a heuristic to
determine which methods are accessors. Specifically, parameter-free ``const``
methods are treated as accessors. Note that this is not guaranteed to be safe
-- but, it is widely used (safely) in practice, and so we have chosen to treat
it as generally safe. Calls to non ``const`` methods are assumed to modify
the state of the object and affect the stability of earlier accessor calls.

Rely on invariants of uncommon APIs
-----------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ using IncludeSpellingStrategy = llvm::Registry<IncludeSpeller>;
std::string spellHeader(const IncludeSpeller::Input &Input);
} // namespace clang::include_cleaner

namespace llvm {
extern template class Registry<clang::include_cleaner::IncludeSpeller>;
} // namespace llvm

#endif
4 changes: 2 additions & 2 deletions clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class ConstTransform : public ClangTidyCheck {
void check(const MatchFinder::MatchResult &Result) override {
const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");
using utils::fixit::addQualifierToVarDecl;
std::optional<FixItHint> Fix = addQualifierToVarDecl(
*D, *Result.Context, DeclSpec::TQ::TQ_const, CT, CP);
std::optional<FixItHint> Fix =
addQualifierToVarDecl(*D, *Result.Context, Qualifiers::Const, CT, CP);
auto Diag = diag(D->getBeginLoc(), "doing const transformation");
if (Fix)
Diag << *Fix;
Expand Down
6 changes: 5 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ Bug Fixes in This Version
- Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685.
- Fixed a crash when diagnosing format strings and encountering an empty
delimited escape sequence (e.g., ``"\o{}"``). #GH102218
- Fixed a crash using ``__array_rank`` on 64-bit targets. (#GH113044).
- The warning emitted for an unsupported register variable type now points to
the unsupported type instead of the ``register`` keyword (#GH109776).

Expand Down Expand Up @@ -507,7 +508,7 @@ Bug Fixes to C++ Support
- Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048)
- Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588)
- Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134)
- A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361)
- A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361), (#GH112352)
- Fixed a crash in the typo correction of an invalid CTAD guide. (#GH107887)
- Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter
pack. (#GH63819), (#GH107560)
Expand Down Expand Up @@ -539,6 +540,9 @@ Bug Fixes to C++ Support
- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)
- During the lookup for a base class name, non-type names are ignored. (#GH16855)
- Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559)
- Clang incorrectly considered a class with an anonymous union member to not be
const-default-constructible even if a union member has a default member initializer.
(#GH95854).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion clang/docs/analyzer/user-docs/CommandLineUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Command Line Usage: scan-build and CodeChecker
==============================================

This document provides guidelines for running the static analyzer from the command line on whole projects.
CodeChecker and scan-build are two CLI tools for using CSA on multiple files (tranlation units).
CodeChecker and scan-build are two CLI tools for using CSA on multiple files (translation units).
Both provide a way of driving the analyzer, detecting compilation flags, and generating reports.
CodeChecker is more actively maintained, provides heuristics for working with multiple versions of popular compilers and it also comes with a web-based GUI for viewing, filtering, categorizing and suppressing the results.
Therefore CodeChecker is recommended in case you need any of the above features or just more customizability in general.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -876,13 +876,13 @@ class CXXTypeidExpr : public Expr {

/// Best-effort check if the expression operand refers to a most derived
/// object. This is not a strong guarantee.
bool isMostDerived(ASTContext &Context) const;
bool isMostDerived(const ASTContext &Context) const;

bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }

/// Retrieves the type operand of this typeid() expression after
/// various required adjustments (removing reference types, cv-qualifiers).
QualType getTypeOperand(ASTContext &Context) const;
QualType getTypeOperand(const ASTContext &Context) const;

/// Retrieve source information for the type operand.
TypeSourceInfo *getTypeOperandSourceInfo() const {
Expand Down
8 changes: 0 additions & 8 deletions clang/include/clang/AST/ExprConcepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,14 +489,6 @@ class NestedRequirement : public Requirement {
return R->getKind() == RK_Nested;
}
};

using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;

/// \brief create a Requirement::SubstitutionDiagnostic with only a
/// SubstitutedEntity and DiagLoc using Sema's allocator.
Requirement::SubstitutionDiagnostic *
createSubstDiagAt(Sema &S, SourceLocation Location, EntityPrinter Printer);

} // namespace concepts

/// C++2a [expr.prim.req]:
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/ASTMatchers/ASTMatchersMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H

#include "clang/Support/Compiler.h"

/// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// ReturnType object.
Expand Down Expand Up @@ -367,7 +369,7 @@
static QualType (T::*value())() const { return &T::FunctionName; } \
}; \
} \
extern const ::clang::ast_matchers::internal:: \
CLANG_ABI extern const ::clang::ast_matchers::internal:: \
TypeTraversePolymorphicMatcher< \
QualType, \
::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
Expand Down Expand Up @@ -407,7 +409,7 @@
static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
}; \
} \
extern const ::clang::ast_matchers::internal:: \
CLANG_ABI extern const ::clang::ast_matchers::internal:: \
TypeTraversePolymorphicMatcher< \
TypeLoc, \
::clang::ast_matchers::internal:: \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
Expand All @@ -39,23 +40,28 @@ struct UncheckedOptionalAccessModelOptions {
bool IgnoreSmartPointerDereference = false;
};

using UncheckedOptionalAccessLattice = CachedConstAccessorsLattice<NoopLattice>;

/// Dataflow analysis that models whether optionals hold values or not.
///
/// Models the `std::optional`, `absl::optional`, and `base::Optional` types.
class UncheckedOptionalAccessModel
: public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> {
: public DataflowAnalysis<UncheckedOptionalAccessModel,
UncheckedOptionalAccessLattice> {
public:
UncheckedOptionalAccessModel(ASTContext &Ctx, dataflow::Environment &Env);

/// Returns a matcher for the optional classes covered by this model.
static ast_matchers::DeclarationMatcher optionalClassDecl();

static NoopLattice initialElement() { return {}; }
static UncheckedOptionalAccessLattice initialElement() { return {}; }

void transfer(const CFGElement &Elt, NoopLattice &L, Environment &Env);
void transfer(const CFGElement &Elt, UncheckedOptionalAccessLattice &L,
Environment &Env);

private:
CFGMatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
CFGMatchSwitch<TransferState<UncheckedOptionalAccessLattice>>
TransferMatchSwitch;
};

class UncheckedOptionalAccessDiagnoser {
Expand All @@ -65,7 +71,8 @@ class UncheckedOptionalAccessDiagnoser {

llvm::SmallVector<SourceLocation>
operator()(const CFGElement &Elt, ASTContext &Ctx,
const TransferStateForDiagnostics<NoopLattice> &State) {
const TransferStateForDiagnostics<UncheckedOptionalAccessLattice>
&State) {
return DiagnoseMatchSwitch(Elt, Ctx, State.Env);
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -2669,7 +2669,7 @@ sign. For example:

.. code-block:: c++

__attribute__((target_clones("sha2+memtag2", "fcma+sve2-pmull128")))
__attribute__((target_clones("sha2+memtag", "fcma+sve2-pmull128")))
void foo() {}

For every multiversioned function a ``default`` (fallback) implementation
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ TARGET_BUILTIN(__builtin_amdgcn_frexp_exph, "sh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "WUi", "n", "s-memrealtime")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp")
TARGET_BUILTIN(__builtin_amdgcn_update_dpp, "iiiIiIiIiIb", "nc", "dpp")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nct", "dpp")
TARGET_BUILTIN(__builtin_amdgcn_update_dpp, "iiiIiIiIiIb", "nct", "dpp")
TARGET_BUILTIN(__builtin_amdgcn_s_dcache_wb, "v", "n", "gfx8-insts")
TARGET_BUILTIN(__builtin_amdgcn_perm, "UiUiUiUi", "nc", "gfx8-insts")

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10188,7 +10188,7 @@ def warn_new_dangling_initializer_list : Warning<
"will be destroyed at the end of the full-expression">,
InGroup<DanglingInitializerList>;
def warn_dangling_pointer_assignment : Warning<
"object backing the pointer %0 "
"object backing %select{|the pointer }0%1 "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingAssignment>;

Expand Down
20 changes: 13 additions & 7 deletions clang/include/clang/Basic/FileManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ class FileManager : public RefCountedBase<FileManager> {
std::unique_ptr<FileSystemStatCache> StatCache;

std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F);
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
bool IsText = true);

/// Add all ancestors of the given path (pointing to either a file
/// or a directory) as virtual directories.
Expand Down Expand Up @@ -230,7 +230,8 @@ class FileManager : public RefCountedBase<FileManager> {
/// the failure to find this file.
llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
bool OpenFile = false,
bool CacheFailure = true);
bool CacheFailure = true,
bool IsText = true);

/// Get the FileEntryRef for stdin, returning an error if stdin cannot be
/// read.
Expand Down Expand Up @@ -290,23 +291,28 @@ class FileManager : public RefCountedBase<FileManager> {

/// Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
/// The IsText parameter controls whether the file should be opened as a text
/// or binary file, and should be set to false if the file contents should be
/// treated as binary.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(FileEntryRef Entry, bool isVolatile = false,
bool RequiresNullTerminator = true,
std::optional<int64_t> MaybeLimit = std::nullopt);
std::optional<int64_t> MaybeLimit = std::nullopt,
bool IsText = true);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(StringRef Filename, bool isVolatile = false,
bool RequiresNullTerminator = true,
std::optional<int64_t> MaybeLimit = std::nullopt) const {
std::optional<int64_t> MaybeLimit = std::nullopt,
bool IsText = true) const {
return getBufferForFileImpl(Filename,
/*FileSize=*/MaybeLimit.value_or(-1),
isVolatile, RequiresNullTerminator);
isVolatile, RequiresNullTerminator, IsText);
}

private:
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile,
bool RequiresNullTerminator) const;
bool RequiresNullTerminator, bool IsText) const;

DirectoryEntry *&getRealDirEntry(const llvm::vfs::Status &Status);

Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Basic/FileSystemStatCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class FileSystemStatCache {
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in \p F with a valid \p File object and
/// the client guarantees that it will close it.
static std::error_code
get(StringRef Path, llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS);
static std::error_code get(StringRef Path, llvm::vfs::Status &Status,
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache,
llvm::vfs::FileSystem &FS, bool IsText = true);

protected:
// FIXME: The pointer here is a non-owning/optional reference to the
Expand Down
16 changes: 13 additions & 3 deletions clang/include/clang/Basic/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace clang {

class FileManager;
class LangOptions;
class ModuleMap;
class TargetInfo;

/// Describes the name of a module.
Expand Down Expand Up @@ -99,6 +100,15 @@ struct ASTFileSignature : std::array<uint8_t, 20> {
}
};

/// Required to construct a Module.
///
/// This tag type is only constructible by ModuleMap, guaranteeing it ownership
/// of all Module instances.
class ModuleConstructorTag {
explicit ModuleConstructorTag() = default;
friend ModuleMap;
};

/// Describes a module or submodule.
///
/// Aligned to 8 bytes to allow for llvm::PointerIntPair<Module *, 3>.
Expand Down Expand Up @@ -497,8 +507,9 @@ class alignas(8) Module {
std::vector<Conflict> Conflicts;

/// Construct a new module or submodule.
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc,
Module *Parent, bool IsFramework, bool IsExplicit,
unsigned VisibilityID);

~Module();

Expand Down Expand Up @@ -749,7 +760,6 @@ class alignas(8) Module {
///
/// \returns The submodule if found, or NULL otherwise.
Module *findSubmodule(StringRef Name) const;
Module *findOrInferSubmodule(StringRef Name);

/// Get the Global Module Fragment (sub-module) for this module, it there is
/// one.
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/ParsedAttrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Registry.h"
#include <climits>
Expand Down Expand Up @@ -175,4 +176,8 @@ const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances();

} // namespace clang

namespace llvm {
extern template class CLANG_TEMPLATE_ABI Registry<clang::ParsedAttrInfo>;
} // namespace llvm

#endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H
12 changes: 5 additions & 7 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ enum class FloatModeKind {
struct TransferrableTargetInfo {
unsigned char PointerWidth, PointerAlign;
unsigned char BoolWidth, BoolAlign;
unsigned char ShortWidth, ShortAlign;
unsigned char IntWidth, IntAlign;
unsigned char HalfWidth, HalfAlign;
unsigned char BFloat16Width, BFloat16Align;
Expand Down Expand Up @@ -497,13 +498,10 @@ class TargetInfo : public TransferrableTargetInfo,
unsigned getCharWidth() const { return 8; } // FIXME
unsigned getCharAlign() const { return 8; } // FIXME

/// Return the size of 'signed short' and 'unsigned short' for this
/// target, in bits.
unsigned getShortWidth() const { return 16; } // FIXME

/// Return the alignment of 'signed short' and 'unsigned short' for
/// this target.
unsigned getShortAlign() const { return 16; } // FIXME
/// getShortWidth/Align - Return the size of 'signed short' and
/// 'unsigned short' for this target, in bits.
unsigned getShortWidth() const { return ShortWidth; }
unsigned getShortAlign() const { return ShortAlign; }

/// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
/// this target, in bits.
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -8102,7 +8102,7 @@ def fnative_half_type: Flag<["-"], "fnative-half-type">,
def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">,
HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">,
MarshallingInfoFlag<LangOpts<"NativeHalfArgsAndReturns">>,
ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath]>;
ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath, hip.KeyPath]>;
def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
HelpText<"Set default calling convention">,
Values<"cdecl,fastcall,stdcall,vectorcall,regcall,rtdcall">,
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Frontend/FrontendPluginRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H

#include "clang/Frontend/FrontendAction.h"
#include "clang/Support/Compiler.h"
#include "llvm/Support/Registry.h"

namespace clang {
Expand All @@ -23,4 +24,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginASTAction>;

} // namespace clang

namespace llvm {
extern template class CLANG_TEMPLATE_ABI Registry<clang::PluginASTAction>;
} // namespace llvm

#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
9 changes: 7 additions & 2 deletions clang/include/clang/Lex/ModuleMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,12 @@ class ModuleMap {
/// named LangOpts::CurrentModule, if we've loaded it).
Module *SourceModule = nullptr;

/// The allocator for all (sub)modules.
llvm::SpecificBumpPtrAllocator<Module> ModulesAlloc;

/// Submodules of the current module that have not yet been attached to it.
/// (Ownership is transferred if/when we create an enclosing module.)
llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
/// (Relationship is set up if/when we create an enclosing module.)
llvm::SmallVector<Module *, 8> PendingSubmodules;

/// The top-level modules that are known.
llvm::StringMap<Module *> Modules;
Expand Down Expand Up @@ -502,6 +505,8 @@ class ModuleMap {
/// \returns The named module, if known; otherwise, returns null.
Module *findModule(StringRef Name) const;

Module *findOrInferSubmodule(Module *Parent, StringRef Name);

/// Retrieve a module with the given name using lexical name lookup,
/// starting at the given context.
///
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "clang/Lex/PPEmbedParameters.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
Expand Down Expand Up @@ -3060,4 +3061,8 @@ using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;

} // namespace clang

namespace llvm {
extern template class CLANG_TEMPLATE_ABI Registry<clang::PragmaHandler>;
} // namespace llvm

#endif // LLVM_CLANG_LEX_PREPROCESSOR_H
7 changes: 7 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -13435,6 +13435,13 @@ class Sema final : public SemaBase {
return CodeSynthesisContexts.size() > NonInstantiationEntries;
}

using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;

/// \brief create a Requirement::SubstitutionDiagnostic with only a
/// SubstitutedEntity and DiagLoc using ASTContext's allocator.
concepts::Requirement::SubstitutionDiagnostic *
createSubstDiagAt(SourceLocation Location, EntityPrinter Printer);

///@}

//
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_CLANG_SERIALIZATION_MODULEFILE_H

#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/ASTBitCodes.h"
Expand Down Expand Up @@ -144,8 +145,8 @@ class ModuleFile {
/// The base directory of the module.
std::string BaseDirectory;

std::string getTimestampFilename() const {
return FileName + ".timestamp";
static std::string getTimestampFilename(StringRef FileName) {
return (FileName + ".timestamp").str();
}

/// The original source file name that was used to build the
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Support/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
#define CLANG_TEMPLATE_ABI __declspec(dllimport)
#define CLANG_EXPORT_TEMPLATE
#endif
#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX)
#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) || \
defined(__MVS__)
#define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
#define CLANG_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
#define CLANG_EXPORT_TEMPLATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H

#include "clang/Support/Compiler.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/Registry.h"

Expand Down Expand Up @@ -42,4 +43,9 @@ using CompilationDatabasePluginRegistry =
} // namespace tooling
} // namespace clang

namespace llvm {
extern template class CLANG_TEMPLATE_ABI
Registry<clang::tooling::CompilationDatabasePlugin>;
} // namespace llvm

#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
6 changes: 6 additions & 0 deletions clang/include/clang/Tooling/ToolExecutorPluginRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H

#include "clang/Support/Compiler.h"
#include "clang/Tooling/Execution.h"
#include "llvm/Support/Registry.h"

Expand All @@ -20,4 +21,9 @@ using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>;
} // namespace tooling
} // namespace clang

namespace llvm {
extern template class CLANG_TEMPLATE_ABI
Registry<clang::tooling::ToolExecutorPlugin>;
} // namespace llvm

#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
91 changes: 51 additions & 40 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,9 +2371,9 @@ bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {

template <class Emitter>
bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
if (std::optional<unsigned> I = P.getOrCreateDummy(E))
return this->emitGetPtrGlobal(*I, E);
return false;
if (DiscardResult)
return true;
return this->emitDummyPtr(E, E);
}

template <class Emitter>
Expand Down Expand Up @@ -3445,11 +3445,8 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
assert(RD);
// If the definiton of the result type is incomplete, just return a dummy.
// If (and when) that is read from, we will fail, but not now.
if (!RD->isCompleteDefinition()) {
if (std::optional<unsigned> I = P.getOrCreateDummy(GuidDecl))
return this->emitGetPtrGlobal(*I, E);
return false;
}
if (!RD->isCompleteDefinition())
return this->emitDummyPtr(GuidDecl, E);

std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(GuidDecl);
if (!GlobalIndex)
Expand Down Expand Up @@ -3687,11 +3684,11 @@ bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
if (!E->isExpressibleAsConstantInitializer())
return this->discard(SubExpr) && this->emitInvalid(E);

assert(classifyPrim(E) == PT_Ptr);
if (std::optional<unsigned> I = P.getOrCreateDummy(E))
return this->emitGetPtrGlobal(*I, E);
if (DiscardResult)
return true;

return false;
assert(classifyPrim(E) == PT_Ptr);
return this->emitDummyPtr(E, E);
}

template <class Emitter>
Expand Down Expand Up @@ -4483,15 +4480,9 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
BuiltinID == Builtin::BI__builtin_function_start) {
if (std::optional<unsigned> GlobalOffset = P.getOrCreateDummy(E)) {
if (!this->emitGetPtrGlobal(*GlobalOffset, E))
return false;

if (PrimType PT = classifyPrim(E); PT != PT_Ptr && isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
if (DiscardResult)
return true;
}
return false;
return this->emitDummyPtr(E, E);
}

QualType ReturnType = E->getType();
Expand Down Expand Up @@ -5738,9 +5729,17 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
// We should already have a pointer when we get here.
return this->delegate(SubExpr);
case UO_Deref: // *x
if (DiscardResult)
if (DiscardResult) {
// assert(false);
return this->discard(SubExpr);
return this->visit(SubExpr);
}

if (!this->visit(SubExpr))
return false;
if (classifyPrim(SubExpr) == PT_Ptr)
return this->emitNarrowPtr(E);
return true;

case UO_Not: // ~x
if (!T)
return this->emitError(E);
Expand Down Expand Up @@ -6089,7 +6088,12 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {

if (VD->evaluateValue())
return revisit(VD);
return this->emitInvalidDeclRef(cast<DeclRefExpr>(E), E);

if (!D->getType()->isReferenceType())
return this->emitDummyPtr(D, E);

return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
/*InitializerFailed=*/true, E);
}
}
} else {
Expand All @@ -6100,23 +6104,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
}

if (std::optional<unsigned> I = P.getOrCreateDummy(D)) {
if (!this->emitGetPtrGlobal(*I, E))
return false;
if (E->getType()->isVoidType())
return true;
// Convert the dummy pointer to another pointer type if we have to.
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
if (isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
return false;
}
return true;
}

if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return this->emitInvalidDeclRef(DRE, E);
return false;
return this->emitDummyPtr(D, E);
}

template <class Emitter>
Expand Down Expand Up @@ -6419,6 +6407,29 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
return this->emitRecordDestruction(Desc->ElemRecord, Loc);
}

/// Create a dummy pointer for the given decl (or expr) and
/// push a pointer to it on the stack.
template <class Emitter>
bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
assert(!DiscardResult && "Should've been checked before");

unsigned DummyID = P.getOrCreateDummy(D);

if (!this->emitGetPtrGlobal(DummyID, E))
return false;
if (E->getType()->isVoidType())
return true;

// Convert the dummy pointer to another pointer type if we have to.
if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
if (isPtrType(PT))
return this->emitDecayPtr(PT_Ptr, PT, E);
return false;
}

return true;
}

namespace clang {
namespace interp {

Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
const BinaryOperator *E);
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
bool emitDummyPtr(const DeclTy &D, const Expr *E);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
Expand Down
25 changes: 18 additions & 7 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1944,14 +1944,14 @@ inline bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC) {

template <class T, ArithOp Op>
bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
const Pointer &Ptr) {
const Pointer &Ptr, bool IsPointerArith = false) {
// A zero offset does not change the pointer.
if (Offset.isZero()) {
S.Stk.push<Pointer>(Ptr);
return true;
}

if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) {
if (IsPointerArith && !CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) {
// The CheckNull will have emitted a note already, but we only
// abort in C++, since this is fine in C.
if (S.getLangOpts().CPlusPlus)
Expand Down Expand Up @@ -2063,14 +2063,16 @@ bool AddOffset(InterpState &S, CodePtr OpPC) {
Pointer Ptr = S.Stk.pop<Pointer>();
if (Ptr.isBlockPointer())
Ptr = Ptr.expand();
return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr);
return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr,
/*IsPointerArith=*/true);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SubOffset(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr);
return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr,
/*IsPointerArith=*/true);
}

template <ArithOp Op>
Expand All @@ -2090,7 +2092,7 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,

// Now the current Ptr again and a constant 1.
OneT One = OneT::from(1);
if (!OffsetHelper<OneT, Op>(S, OpPC, One, P))
if (!OffsetHelper<OneT, Op>(S, OpPC, One, P, /*IsPointerArith=*/true))
return false;

// Store the new value.
Expand Down Expand Up @@ -2816,9 +2818,18 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
return false;
}

inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC,
const DeclRefExpr *DR) {
inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR,
bool InitializerFailed) {
assert(DR);

if (InitializerFailed) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
const auto *VD = cast<VarDecl>(DR->getDecl());
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
return false;
}

return CheckDeclRef(S, OpPC, DR);
}

Expand Down
12 changes: 12 additions & 0 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,10 @@ static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
APSInt Val = peekToAPSInt(S.Stk, ValT,
Expand Down Expand Up @@ -1331,6 +1335,10 @@ static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));

Expand All @@ -1352,6 +1360,10 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ def InvalidCast : Opcode {
}

def InvalidDeclRef : Opcode {
let Args = [ArgDeclRef];
let Args = [ArgDeclRef, ArgBool];
}

def SizelessVectorElementSize : Opcode;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,

// Return the composite type.
APValue Result;
if (!Composite(getType(), *this, Result))
if (!Composite(ResultType, *this, Result))
return std::nullopt;
return Result;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
return std::nullopt;
}

std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {
unsigned Program::getOrCreateDummy(const DeclTy &D) {
assert(D);
// Dedup blocks since they are immutable and pointers cannot be compared.
if (auto It = DummyVariables.find(D.getOpaqueValue());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Program final {
const Expr *Init = nullptr);

/// Returns or creates a dummy value for unknown declarations.
std::optional<unsigned> getOrCreateDummy(const DeclTy &D);
unsigned getOrCreateDummy(const DeclTy &D);

/// Creates a global and returns its index.
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *Init);
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (isUnion() && !Field->isAnonymousStructOrUnion())
data().HasVariantMembers = true;

if (isUnion() && IsFirstField)
data().HasUninitializedFields = true;

// C++0x [class]p9:
// A POD struct is a class that is both a trivial class and a
// standard-layout class, and has no non-static data members of type
Expand Down Expand Up @@ -1128,7 +1131,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedCopyConstructorIsDeleted = true;
}

if (!Field->hasInClassInitializer() && !Field->isMutable()) {
if (isUnion() && !Field->isMutable()) {
if (Field->hasInClassInitializer())
data().HasUninitializedFields = false;
} else if (!Field->hasInClassInitializer() && !Field->isMutable()) {
if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
data().HasUninitializedFields = true;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ bool CXXTypeidExpr::isPotentiallyEvaluated() const {
return false;
}

bool CXXTypeidExpr::isMostDerived(ASTContext &Context) const {
bool CXXTypeidExpr::isMostDerived(const ASTContext &Context) const {
assert(!isTypeOperand() && "Cannot call isMostDerived for typeid(type)");
const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context);
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
Expand All @@ -159,7 +159,7 @@ bool CXXTypeidExpr::isMostDerived(ASTContext &Context) const {
return false;
}

QualType CXXTypeidExpr::getTypeOperand(ASTContext &Context) const {
QualType CXXTypeidExpr::getTypeOperand(const ASTContext &Context) const {
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
Qualifiers Quals;
return Context.getUnqualifiedArrayType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/Formula.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Analysis/FlowSensitive/RecordOps.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/SourceLocation.h"
Expand Down Expand Up @@ -104,10 +105,17 @@ static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) {
return nullptr;
}

static bool isSupportedOptionalType(QualType Ty) {
const CXXRecordDecl *Optional =
getOptionalBaseClass(Ty->getAsCXXRecordDecl());
return Optional != nullptr;
}

namespace {

using namespace ::clang::ast_matchers;
using LatticeTransferState = TransferState<NoopLattice>;

using LatticeTransferState = TransferState<UncheckedOptionalAccessLattice>;

AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); }

Expand Down Expand Up @@ -325,6 +333,19 @@ auto isValueOrNotEqX() {
ComparesToSame(integerLiteral(equals(0)))));
}

auto isZeroParamConstMemberCall() {
return cxxMemberCallExpr(
callee(cxxMethodDecl(parameterCountIs(0), isConst())));
}

auto isNonConstMemberCall() {
return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst()))));
}

auto isNonConstMemberOperatorCall() {
return cxxOperatorCallExpr(callee(cxxMethodDecl(unless(isConst()))));
}

auto isCallReturningOptional() {
return callExpr(hasType(qualType(
anyOf(desugarsToOptionalOrDerivedType(),
Expand Down Expand Up @@ -523,6 +544,99 @@ void transferCallReturningOptional(const CallExpr *E,
setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
}

void handleConstMemberCall(const CallExpr *CE,
dataflow::RecordStorageLocation *RecordLoc,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
// If the const method returns an optional or reference to an optional.
if (RecordLoc != nullptr && isSupportedOptionalType(CE->getType())) {
StorageLocation *Loc =
State.Lattice.getOrCreateConstMethodReturnStorageLocation(
*RecordLoc, CE, State.Env, [&](StorageLocation &Loc) {
setHasValue(cast<RecordStorageLocation>(Loc),
State.Env.makeAtomicBoolValue(), State.Env);
});
if (Loc == nullptr)
return;
if (CE->isGLValue()) {
// If the call to the const method returns a reference to an optional,
// link the call expression to the cached StorageLocation.
State.Env.setStorageLocation(*CE, *Loc);
} else {
// If the call to the const method returns an optional by value, we
// need to use CopyRecord to link the optional to the result object
// of the call expression.
auto &ResultLoc = State.Env.getResultObjectLocation(*CE);
copyRecord(*cast<RecordStorageLocation>(Loc), ResultLoc, State.Env);
}
return;
}

// Cache if the const method returns a boolean type.
// We may decide to cache other return types in the future.
if (RecordLoc != nullptr && CE->getType()->isBooleanType()) {
Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(*RecordLoc, CE,
State.Env);
if (Val == nullptr)
return;
State.Env.setValue(*CE, *Val);
return;
}

// Perform default handling if the call returns an optional
// but wasn't handled above (if RecordLoc is nullptr).
if (isSupportedOptionalType(CE->getType())) {
transferCallReturningOptional(CE, Result, State);
}
}

void transferValue_ConstMemberCall(const CXXMemberCallExpr *MCE,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
handleConstMemberCall(
MCE, dataflow::getImplicitObjectLocation(*MCE, State.Env), Result, State);
}

void handleNonConstMemberCall(const CallExpr *CE,
dataflow::RecordStorageLocation *RecordLoc,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
// When a non-const member function is called, reset some state.
if (RecordLoc != nullptr) {
for (const auto &[Field, FieldLoc] : RecordLoc->children()) {
if (isSupportedOptionalType(Field->getType())) {
auto *FieldRecordLoc = cast_or_null<RecordStorageLocation>(FieldLoc);
if (FieldRecordLoc) {
setHasValue(*FieldRecordLoc, State.Env.makeAtomicBoolValue(),
State.Env);
}
}
}
State.Lattice.clearConstMethodReturnValues(*RecordLoc);
State.Lattice.clearConstMethodReturnStorageLocations(*RecordLoc);
}

// Perform default handling if the call returns an optional.
if (isSupportedOptionalType(CE->getType())) {
transferCallReturningOptional(CE, Result, State);
}
}

void transferValue_NonConstMemberCall(const CXXMemberCallExpr *MCE,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
handleNonConstMemberCall(
MCE, dataflow::getImplicitObjectLocation(*MCE, State.Env), Result, State);
}

void transferValue_NonConstMemberOperatorCall(
const CXXOperatorCallExpr *OCE, const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
auto *RecordLoc = cast_or_null<dataflow::RecordStorageLocation>(
State.Env.getStorageLocation(*OCE->getArg(0)));
handleNonConstMemberCall(OCE, RecordLoc, Result, State);
}

void constructOptionalValue(const Expr &E, Environment &Env,
BoolValue &HasValueVal) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(E);
Expand Down Expand Up @@ -899,7 +1013,17 @@ auto buildTransferMatchSwitch() {
transferOptionalAndValueCmp(Cmp, Cmp->getArg(1), State.Env);
})

// returns optional
// const accessor calls
.CaseOfCFGStmt<CXXMemberCallExpr>(isZeroParamConstMemberCall(),
transferValue_ConstMemberCall)
// non-const member calls that may modify the state of an object.
.CaseOfCFGStmt<CXXMemberCallExpr>(isNonConstMemberCall(),
transferValue_NonConstMemberCall)
.CaseOfCFGStmt<CXXOperatorCallExpr>(
isNonConstMemberOperatorCall(),
transferValue_NonConstMemberOperatorCall)

// other cases of returning optional
.CaseOfCFGStmt<CallExpr>(isCallReturningOptional(),
transferCallReturningOptional)

Expand Down Expand Up @@ -958,7 +1082,8 @@ UncheckedOptionalAccessModel::optionalClassDecl() {

UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx,
Environment &Env)
: DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice>(Ctx),
: DataflowAnalysis<UncheckedOptionalAccessModel,
UncheckedOptionalAccessLattice>(Ctx),
TransferMatchSwitch(buildTransferMatchSwitch()) {
Env.getDataflowAnalysisContext().setSyntheticFieldCallback(
[&Ctx](QualType Ty) -> llvm::StringMap<QualType> {
Expand All @@ -972,7 +1097,8 @@ UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx,
}

void UncheckedOptionalAccessModel::transfer(const CFGElement &Elt,
NoopLattice &L, Environment &Env) {
UncheckedOptionalAccessLattice &L,
Environment &Env) {
LatticeTransferState State(L, Env);
TransferMatchSwitch(Elt, getASTContext(), State);
}
Expand Down
34 changes: 19 additions & 15 deletions clang/lib/Basic/FileManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,10 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
return llvm::errorToErrorCode(Result.takeError());
}

llvm::Expected<FileEntryRef>
FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
llvm::Expected<FileEntryRef> FileManager::getFileRef(StringRef Filename,
bool openFile,
bool CacheFailure,
bool IsText) {
++NumFileLookups;

// See if there is already an entry in the map.
Expand Down Expand Up @@ -259,7 +261,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
std::unique_ptr<llvm::vfs::File> F;
llvm::vfs::Status Status;
auto statError = getStatValue(InterndFileName, Status, true,
openFile ? &F : nullptr);
openFile ? &F : nullptr, IsText);
if (statError) {
// There's no real file at the given path.
if (CacheFailure)
Expand Down Expand Up @@ -531,7 +533,7 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile,
bool RequiresNullTerminator,
std::optional<int64_t> MaybeLimit) {
std::optional<int64_t> MaybeLimit, bool IsText) {
const FileEntry *Entry = &FE.getFileEntry();
// If the content is living on the file entry, return a reference to it.
if (Entry->Content)
Expand All @@ -558,42 +560,44 @@ FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile,

// Otherwise, open the file.
return getBufferForFileImpl(Filename, FileSize, isVolatile,
RequiresNullTerminator);
RequiresNullTerminator, IsText);
}

llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize,
bool isVolatile,
bool RequiresNullTerminator) const {
bool isVolatile, bool RequiresNullTerminator,
bool IsText) const {
if (FileSystemOpts.WorkingDir.empty())
return FS->getBufferForFile(Filename, FileSize, RequiresNullTerminator,
isVolatile);
isVolatile, IsText);

SmallString<128> FilePath(Filename);
FixupRelativePath(FilePath);
return FS->getBufferForFile(FilePath, FileSize, RequiresNullTerminator,
isVolatile);
isVolatile, IsText);
}

/// getStatValue - Get the 'stat' information for the specified path,
/// using the cache to accelerate it if possible. This returns true
/// if the path points to a virtual file or does not exist, or returns
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
std::error_code
FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status,
bool isFile, std::unique_ptr<llvm::vfs::File> *F) {
std::error_code FileManager::getStatValue(StringRef Path,
llvm::vfs::Status &Status,
bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
bool IsText) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
if (FileSystemOpts.WorkingDir.empty())
return FileSystemStatCache::get(Path, Status, isFile, F,
StatCache.get(), *FS);
return FileSystemStatCache::get(Path, Status, isFile, F, StatCache.get(),
*FS, IsText);

SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);

return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F,
StatCache.get(), *FS);
StatCache.get(), *FS, IsText);
}

std::error_code
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/Basic/FileSystemStatCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ void FileSystemStatCache::anchor() {}
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
std::error_code
FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status,
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache,
llvm::vfs::FileSystem &FS) {
std::error_code FileSystemStatCache::get(StringRef Path,
llvm::vfs::Status &Status, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
FileSystemStatCache *Cache,
llvm::vfs::FileSystem &FS,
bool IsText) {
bool isForDir = !isFile;
std::error_code RetCode;

Expand All @@ -58,7 +59,8 @@ FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status,
//
// Because of this, check to see if the file exists with 'open'. If the
// open succeeds, use fstat to get the stat info.
auto OwnedFile = FS.openFileForRead(Path);
auto OwnedFile =
IsText ? FS.openFileForRead(Path) : FS.openFileForReadBinary(Path);

if (!OwnedFile) {
// If the open fails, our "stat" fails.
Expand Down
26 changes: 4 additions & 22 deletions clang/lib/Basic/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@

using namespace clang;

Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
Module::Module(ModuleConstructorTag, StringRef Name,
SourceLocation DefinitionLoc, Module *Parent, bool IsFramework,
bool IsExplicit, unsigned VisibilityID)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
VisibilityID(VisibilityID), IsUnimportable(false),
HasIncompatibleModuleFile(false), IsAvailable(true),
Expand All @@ -58,11 +59,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
}
}

Module::~Module() {
for (auto *Submodule : SubModules) {
delete Submodule;
}
}
Module::~Module() = default;

static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
StringRef Platform = Target.getPlatformName();
Expand Down Expand Up @@ -361,21 +358,6 @@ Module *Module::findSubmodule(StringRef Name) const {
return SubModules[Pos->getValue()];
}

Module *Module::findOrInferSubmodule(StringRef Name) {
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
if (Pos != SubModuleIndex.end())
return SubModules[Pos->getValue()];
if (!InferSubmodules)
return nullptr;
Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
Result->InferExplicitSubmodules = InferExplicitSubmodules;
Result->InferSubmodules = InferSubmodules;
Result->InferExportWildcard = InferExportWildcard;
if (Result->InferExportWildcard)
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
return Result;
}

Module *Module::getGlobalModuleFragment() const {
assert(isNamedModuleUnit() && "We should only query the global module "
"fragment from the C++20 Named modules");
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
HasStrictFP = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
ShortWidth = ShortAlign = 16;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
Expand Down Expand Up @@ -437,6 +438,7 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
// what these normally are for the target.
// We also define long long and long double here, although the
// OpenCL standard only mentions these as "reserved".
ShortWidth = ShortAlign = 16;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 64;
LongLongWidth = LongLongAlign = 128;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Case("sme-fa64", HasSMEFA64)
.Case("sme-f16f16", HasSMEF16F16)
.Case("sme-b16b16", HasSMEB16B16)
.Cases("memtag", "memtag2", HasMTE)
.Case("memtag", HasMTE)
.Case("sb", HasSB)
.Case("predres", HasPredRes)
.Cases("ssbs", "ssbs2", HasSSBS)
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Basic/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,9 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
TargetInfo::adjust(Diags, Opts);
// ToDo: There are still a few places using default address space as private
// address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL
// can be removed from the following line.
setAddressSpaceMap(/*DefaultIsPrivate=*/Opts.OpenCL ||
// address space in OpenCL, which needs to be cleaned up, then the references
// to OpenCL can be removed from the following line.
setAddressSpaceMap((Opts.OpenCL && !Opts.OpenCLGenericAddressSpace) ||
!isAMDGCN(getTriple()));
}

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AVR.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
TLSSupported = false;
PointerWidth = 16;
PointerAlign = 8;
ShortWidth = 16;
ShortAlign = 8;
IntWidth = 16;
IntAlign = 8;
LongWidth = 32;
Expand Down Expand Up @@ -65,6 +67,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
return std::nullopt;
}

bool allowsLargerPreferedTypeAlignment() const override { return false; }

BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,8 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
DI->setLocation(D->getLocation());
DI->EmitDeclareOfBlockLiteralArgVariable(
*BlockInfo, D->getName(), argNum,
cast<llvm::AllocaInst>(alloc.getPointer()), Builder);
cast<llvm::AllocaInst>(alloc.getPointer()->stripPointerCasts()),
Builder);
}
}

Expand Down
42 changes: 33 additions & 9 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5853,8 +5853,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
/*IndexTypeQuals=*/0);
auto Tmp = CreateMemTemp(SizeArrayTy, "block_sizes");
llvm::Value *TmpPtr = Tmp.getPointer();
// The EmitLifetime* pair expect a naked Alloca as their last argument,
// however for cases where the default AS is not the Alloca AS, Tmp is
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
llvm::Value *TmpSize = EmitLifetimeStart(
CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), TmpPtr);
CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
Expand All @@ -5870,7 +5875,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.CreateAlignedStore(
V, GEP, CGM.getDataLayout().getPrefTypeAlign(SizeTy));
}
return std::tie(ElemPtr, TmpSize, TmpPtr);
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
return std::tie(ElemPtr, TmpSize, Alloca);
};

// Could have events and/or varargs.
Expand Down Expand Up @@ -19037,15 +19044,32 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
ASTContext::GetBuiltinTypeError Error;
getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
assert(Error == ASTContext::GE_None && "Should not codegen an error");
llvm::Type *DataTy = ConvertType(E->getArg(0)->getType());
unsigned Size = DataTy->getPrimitiveSizeInBits();
llvm::Type *IntTy =
llvm::IntegerType::get(Builder.getContext(), std::max(Size, 32u));
Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, IntTy);
assert(E->getNumArgs() == 5 || E->getNumArgs() == 6);
bool InsertOld = E->getNumArgs() == 5;
if (InsertOld)
Args.push_back(llvm::PoisonValue::get(IntTy));
for (unsigned I = 0; I != E->getNumArgs(); ++I) {
Args.push_back(EmitScalarOrConstFoldImmArg(ICEArguments, I, E));
llvm::Value *V = EmitScalarOrConstFoldImmArg(ICEArguments, I, E);
if (I <= !InsertOld && Size < 32) {
if (!DataTy->isIntegerTy())
V = Builder.CreateBitCast(
V, llvm::IntegerType::get(Builder.getContext(), Size));
V = Builder.CreateZExtOrBitCast(V, IntTy);
}
llvm::Type *ExpTy =
F->getFunctionType()->getFunctionParamType(I + InsertOld);
Args.push_back(Builder.CreateTruncOrBitCast(V, ExpTy));
}
assert(Args.size() == 5 || Args.size() == 6);
if (Args.size() == 5)
Args.insert(Args.begin(), llvm::PoisonValue::get(Args[0]->getType()));
Function *F =
CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, Args[0]->getType());
return Builder.CreateCall(F, Args);
Value *V = Builder.CreateCall(F, Args);
if (Size < 32 && !DataTy->isIntegerTy())
V = Builder.CreateTrunc(
V, llvm::IntegerType::get(Builder.getContext(), Size));
return Builder.CreateTruncOrBitCast(V, DataTy);
}
case AMDGPU::BI__builtin_amdgcn_permlane16:
case AMDGPU::BI__builtin_amdgcn_permlanex16:
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/CodeGen/CGDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,10 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
getLangOpts().GPUAllowDeviceInit);
if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
if (getTriple().isSPIRV())
Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
else
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
Fn->addFnAttr("device-init");
}

Expand Down Expand Up @@ -973,7 +976,10 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
getLangOpts().GPUAllowDeviceInit);
if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
if (getTriple().isSPIRV())
Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
else
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
Fn->addFnAttr("device-init");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ class ScalarExprEmitter
}

Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue());
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}

Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
Expand Down
9 changes: 4 additions & 5 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2904,19 +2904,18 @@ void CodeGenFunction::EmitMultiVersionResolver(
}
}

static int getPriorityFromAttrString(StringRef AttrStr) {
static unsigned getPriorityFromAttrString(StringRef AttrStr) {
SmallVector<StringRef, 8> Attrs;

AttrStr.split(Attrs, ';');

// Default Priority is zero.
int Priority = 0;
unsigned Priority = 0;
for (auto Attr : Attrs) {
if (Attr.consume_front("priority=")) {
int Result;
if (!Attr.getAsInteger(0, Result)) {
unsigned Result;
if (!Attr.getAsInteger(0, Result))
Priority = Result;
}
}
}

Expand Down
46 changes: 17 additions & 29 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,12 +1098,6 @@ struct CounterCoverageMappingBuilder
return ExitCount;
}

/// Determine whether the given condition can be constant folded.
bool ConditionFoldsToBool(const Expr *Cond) {
Expr::EvalResult Result;
return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
}

/// Create a Branch Region around an instrumentable condition for coverage
/// and add it to the function's SourceRegions. A branch region tracks a
/// "True" counter and a "False" counter for boolean expressions that
Expand Down Expand Up @@ -1133,13 +1127,15 @@ struct CounterCoverageMappingBuilder
// Alternatively, we can prevent any optimization done via
// constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
// CodeGenFunction.c always returns false, but that is very heavy-handed.
if (ConditionFoldsToBool(C))
popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
Counter::getZero(), BranchParams));
else
// Otherwise, create a region with the True counter and False counter.
popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt,
BranchParams));
Expr::EvalResult Result;
if (C->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())) {
if (Result.Val.getInt().getBoolValue())
FalseCnt = Counter::getZero();
else
TrueCnt = Counter::getZero();
}
popRegions(
pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, BranchParams));
}
}

Expand All @@ -1153,12 +1149,12 @@ struct CounterCoverageMappingBuilder

/// Create a Branch Region around a SwitchCase for code coverage
/// and add it to the function's SourceRegions.
void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
Counter FalseCnt) {
void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt) {
// Push region onto RegionStack but immediately pop it (which adds it to
// the function's SourceRegions) because it doesn't apply to any other
// source other than the SwitchCase.
popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(),
Counter::getZero()));
}

/// Check whether a region with bounds \c StartLoc and \c EndLoc
Expand Down Expand Up @@ -1870,24 +1866,16 @@ struct CounterCoverageMappingBuilder
const SwitchCase *Case = S->getSwitchCaseList();
for (; Case; Case = Case->getNextSwitchCase()) {
HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
CaseCountSum =
addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
createSwitchCaseRegion(
Case, getRegionCounter(Case),
subtractCounters(ParentCount, getRegionCounter(Case)));
auto CaseCount = getRegionCounter(Case);
CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false);
createSwitchCaseRegion(Case, CaseCount);
}
// Simplify is skipped while building the counters above: it can get really
// slow on top of switches with thousands of cases. Instead, trigger
// simplification by adding zero to the last counter.
CaseCountSum = addCounters(CaseCountSum, Counter::getZero());

// If no explicit default case exists, create a branch region to represent
// the hidden branch, which will be added later by the CodeGen. This region
// will be associated with the switch statement's condition.
if (!HasDefaultCase) {
Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
Counter DefaultCount = subtractCounters(ParentCount, CaseCountSum);
createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount);
}
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getNVPTXTargetFeatures(C.getDriver(), getToolChain().getTriple(), Args,
Features);
CmdArgs.push_back(
Args.MakeArgString("--plugin-opt=mattr=" + llvm::join(Features, ",")));
Args.MakeArgString("--plugin-opt=-mattr=" + llvm::join(Features, ",")));

// Add paths for the default clang library path.
SmallString<256> DefaultLibPath =
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2148,7 +2148,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() {
if (!Style.isCSharp())
return false;
// See if it's a property accessor.
if (FormatTok->Previous->isNot(tok::identifier))
if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
return false;

// See if we are inside a property accessor.
Expand Down Expand Up @@ -3484,10 +3484,10 @@ bool UnwrappedLineParser::parseRequires() {
case tok::r_paren:
case tok::kw_noexcept:
case tok::kw_const:
case tok::amp:
// This is a requires clause.
parseRequiresClause(RequiresToken);
return true;
case tok::amp:
case tok::ampamp: {
// This can be either:
// if (... && requires (T t) ...)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/opencl-c-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#define __opencl_c_ext_fp32_global_atomic_min_max 1
#define __opencl_c_ext_fp32_local_atomic_min_max 1
#define __opencl_c_ext_image_raw10_raw12 1
#define __opencl_c_ext_image_unorm_int_2_101010 1
#define cl_khr_kernel_clock 1
#define __opencl_c_kernel_clock_scope_device 1
#define __opencl_c_kernel_clock_scope_work_group 1
Expand Down Expand Up @@ -486,6 +487,9 @@ typedef enum memory_order
#define CLK_UNSIGNED_INT_RAW10_EXT 0x10E3
#define CLK_UNSIGNED_INT_RAW12_EXT 0x10E4
#endif // __opencl_c_ext_image_raw10_raw12
#ifdef __opencl_c_ext_image_unorm_int_2_101010
#define CLK_UNORM_INT_2_101010_EXT 0x10E5
#endif // __opencl_c_ext_image_unorm_int_2_101010

// Channel order, numbering must be aligned with cl_channel_order in cl.h
//
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Lex/HeaderMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ std::unique_ptr<HeaderMap> HeaderMap::Create(FileEntryRef FE, FileManager &FM) {
unsigned FileSize = FE.getSize();
if (FileSize <= sizeof(HMapHeader)) return nullptr;

auto FileBuffer = FM.getBufferForFile(FE);
auto FileBuffer =
FM.getBufferForFile(FE, /*IsVolatile=*/false,
/*RequiresNullTerminator=*/true,
/*MaybeList=*/std::nullopt, /*IsText=*/false);
if (!FileBuffer || !*FileBuffer)
return nullptr;
bool NeedsByteSwap;
Expand Down
72 changes: 42 additions & 30 deletions clang/lib/Lex/ModuleMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
MMapLangOpts.LineComment = true;
}

ModuleMap::~ModuleMap() {
for (auto &M : Modules)
delete M.getValue();
for (auto *M : ShadowModules)
delete M;
}
ModuleMap::~ModuleMap() = default;

void ModuleMap::setTarget(const TargetInfo &Target) {
assert((!this->Target || this->Target == &Target) &&
Expand Down Expand Up @@ -831,6 +826,22 @@ Module *ModuleMap::findModule(StringRef Name) const {
return nullptr;
}

Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
if (Module *SubM = Parent->findSubmodule(Name))
return SubM;
if (!Parent->InferSubmodules)
return nullptr;
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
Parent->InferExplicitSubmodules, 0);
Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
Result->InferSubmodules = Parent->InferSubmodules;
Result->InferExportWildcard = Parent->InferExportWildcard;
if (Result->InferExportWildcard)
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
return Result;
}

Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
Module *Context) const {
for(; Context; Context = Context->Parent) {
Expand All @@ -857,8 +868,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
return std::make_pair(Sub, false);

// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
IsExplicit, NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
IsFramework, IsExplicit, NumCreatedModules++);
if (!Parent) {
if (LangOpts.CurrentModule == Name)
SourceModule = Result;
Expand All @@ -870,8 +882,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,

Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
Module *Parent) {
auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate()) Module(
ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/true, NumCreatedModules++);
Result->Kind = Module::ExplicitGlobalModuleFragment;
// If the created module isn't owned by a parent, send it to PendingSubmodules
// to wait for its parent.
Expand All @@ -888,35 +901,33 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
// Note: Here the `IsExplicit` parameter refers to the semantics in clang
// modules. All the non-explicit submodules in clang modules will be exported
// too. Here we simplify the implementation by using the concept.
auto *Result =
new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
/*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Module::ImplicitGlobalModuleFragment;
return Result;
}

Module *
ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
SourceLocation Loc) {
auto *Result =
new Module("<private>", Loc, Parent, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate()) Module(
ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/true, NumCreatedModules++);
Result->Kind = Module::PrivateModuleFragment;
return Result;
}

Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
Module::ModuleKind Kind) {
auto *Result =
new Module(Name, Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Kind;

// Reparent any current global module fragment as a submodule of this module.
for (auto &Submodule : PendingSubmodules) {
for (auto &Submodule : PendingSubmodules)
Submodule->setParent(Result);
Submodule.release(); // now owned by parent
}
PendingSubmodules.clear();
return Result;
}
Expand Down Expand Up @@ -968,8 +979,9 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
assert(LangOpts.CurrentModule == Name && "module name mismatch");
assert(!Modules[Name] && "redefining existing module");

auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Module::ModuleHeaderUnit;
Modules[Name] = SourceModule = Result;
addHeader(Result, H, NormalHeader);
Expand Down Expand Up @@ -1082,9 +1094,9 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
if (!UmbrellaHeader)
return nullptr;

Module *Result = new Module(ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false,
NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
InferredModuleAllowedBy[Result] = ModuleMapFID;
Result->IsInferred = true;
if (!Parent) {
Expand Down Expand Up @@ -1173,9 +1185,9 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
Module *ShadowingModule) {

// Create a new module with this name.
Module *Result =
new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
/*IsExplicit=*/false, NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
Result->ShadowingModule = ShadowingModule;
Result->markUnavailable(/*Unimportable*/true);
ModuleScopeIDs[Result] = CurrentModuleScopeID;
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Lex/PPDirectives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,8 +1080,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
FileManager &FM = this->getFileManager();
if (llvm::sys::path::is_absolute(Filename)) {
// lookup path or immediately fail
llvm::Expected<FileEntryRef> ShouldBeEntry =
FM.getFileRef(Filename, OpenFile);
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
Filename, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
return llvm::expectedToOptional(std::move(ShouldBeEntry));
}

Expand All @@ -1107,8 +1107,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
StringRef FullFileDir = LookupFromFile->tryGetRealPathName();
if (!FullFileDir.empty()) {
SeparateComponents(LookupPath, FullFileDir, Filename, true);
llvm::Expected<FileEntryRef> ShouldBeEntry =
FM.getFileRef(LookupPath, OpenFile);
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
if (ShouldBeEntry)
return llvm::expectedToOptional(std::move(ShouldBeEntry));
llvm::consumeError(ShouldBeEntry.takeError());
Expand All @@ -1123,8 +1123,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
StringRef WorkingDir = WorkingDirEntry.getName();
if (!WorkingDir.empty()) {
SeparateComponents(LookupPath, WorkingDir, Filename, false);
llvm::Expected<FileEntryRef> ShouldBeEntry =
FM.getFileRef(LookupPath, OpenFile);
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
if (ShouldBeEntry)
return llvm::expectedToOptional(std::move(ShouldBeEntry));
llvm::consumeError(ShouldBeEntry.takeError());
Expand All @@ -1135,8 +1135,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
for (const auto &Entry : PPOpts->EmbedEntries) {
LookupPath.clear();
SeparateComponents(LookupPath, Entry, Filename, false);
llvm::Expected<FileEntryRef> ShouldBeEntry =
FM.getFileRef(LookupPath, OpenFile);
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
if (ShouldBeEntry)
return llvm::expectedToOptional(std::move(ShouldBeEntry));
llvm::consumeError(ShouldBeEntry.takeError());
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Lex/Pragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1752,14 +1752,15 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// Find the module we're entering. We require that a module map for it
// be loaded or implicitly loadable.
auto &HSI = PP.getHeaderSearchInfo();
auto &MM = HSI.getModuleMap();
Module *M = HSI.lookupModule(Current, ModuleName.front().second);
if (!M) {
PP.Diag(ModuleName.front().second,
diag::err_pp_module_begin_no_module_map) << Current;
return;
}
for (unsigned I = 1; I != ModuleName.size(); ++I) {
auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName());
auto *NewM = MM.findOrInferSubmodule(M, ModuleName[I].first->getName());
if (!NewM) {
PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule)
<< M->getFullModuleName() << ModuleName[I].first;
Expand Down
12 changes: 7 additions & 5 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3148,11 +3148,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(
// we did nothing here, but this allows us to issue a more
// helpful diagnostic.
if (Tok.is(tok::kw_concept)) {
Diag(Tok.getLocation(),
DS.isFriendSpecified() || NextToken().is(tok::kw_friend)
? diag::err_friend_concept
: diag::
err_concept_decls_may_only_appear_in_global_namespace_scope);
Diag(
Tok.getLocation(),
DS.isFriendSpecified() || NextToken().is(tok::kw_friend)
? llvm::to_underlying(diag::err_friend_concept)
: llvm::to_underlying(
diag::
err_concept_decls_may_only_appear_in_global_namespace_scope));
SkipUntil(tok::semi, tok::r_brace, StopBeforeMatch);
return nullptr;
}
Expand Down
22 changes: 15 additions & 7 deletions clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1206,11 +1206,13 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
assert(shouldLifetimeExtendThroughPath(Path) ==
PathLifetimeKind::NoExtend &&
"No lifetime extension for assignments");
SemaRef.Diag(DiagLoc,
IsGslPtrValueFromGslTempOwner
? diag::warn_dangling_lifetime_pointer_assignment
: diag::warn_dangling_pointer_assignment)
<< AEntity->LHS << DiagRange;
if (IsGslPtrValueFromGslTempOwner)
SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
<< AEntity->LHS << DiagRange;
else
SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
<< AEntity->LHS->getType()->isPointerType() << AEntity->LHS
<< DiagRange;
return false;
}
case LK_MemInitializer: {
Expand Down Expand Up @@ -1412,8 +1414,14 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
};

llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
if (LK == LK_Assignment && shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity))
Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init});
if (LK == LK_Assignment &&
shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) {
Path.push_back(
{isAssignmentOperatorLifetimeBound(AEntity->AssignmentOperator)
? IndirectLocalPathEntry::LifetimeBoundCall
: IndirectLocalPathEntry::GslPointerAssignment,
Init});
}

if (Init->isGLValue())
visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
Expand Down
44 changes: 44 additions & 0 deletions clang/lib/Sema/SemaAMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,50 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
OrderIndex = 0;
ScopeIndex = 1;
break;
case AMDGPU::BI__builtin_amdgcn_mov_dpp: {
if (SemaRef.checkArgCountRange(TheCall, 5, 5))
return true;
Expr *ValArg = TheCall->getArg(0);
QualType Ty = ValArg->getType();
// TODO: Vectors can also be supported.
if (!Ty->isArithmeticType() || Ty->isAnyComplexType()) {
SemaRef.Diag(ValArg->getBeginLoc(),
diag::err_typecheck_cond_expect_int_float)
<< Ty << ValArg->getSourceRange();
return true;
}
return false;
}
case AMDGPU::BI__builtin_amdgcn_update_dpp: {
if (SemaRef.checkArgCountRange(TheCall, 6, 6))
return true;
Expr *Args[2];
QualType ArgTys[2];
for (unsigned I = 0; I != 2; ++I) {
Args[I] = TheCall->getArg(I);
ArgTys[I] = Args[I]->getType();
// TODO: Vectors can also be supported.
if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
SemaRef.Diag(Args[I]->getBeginLoc(),
diag::err_typecheck_cond_expect_int_float)
<< ArgTys[I] << Args[I]->getSourceRange();
return true;
}
}
if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
return false;
if (((ArgTys[0]->isUnsignedIntegerType() &&
ArgTys[1]->isSignedIntegerType()) ||
(ArgTys[0]->isSignedIntegerType() &&
ArgTys[1]->isUnsignedIntegerType())) &&
getASTContext().getTypeSize(ArgTys[0]) ==
getASTContext().getTypeSize(ArgTys[1]))
return false;
SemaRef.Diag(Args[1]->getBeginLoc(),
diag::err_typecheck_call_different_arg_types)
<< ArgTys[0] << ArgTys[1];
return true;
}
default:
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3072,7 +3072,7 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
if (HasPriority)
DuplicateAttr = true;
HasPriority = true;
int Digit;
unsigned Digit;
if (AttrStr.getAsInteger(0, Digit))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
Expand Down Expand Up @@ -3226,7 +3226,7 @@ bool Sema::checkTargetClonesAttrString(
HasDefault = true;
} else if (AttrStr.consume_front("priority=")) {
IsPriority = true;
int Digit;
unsigned Digit;
if (AttrStr.getAsInteger(0, Digit))
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Str << TargetClones;
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9444,11 +9444,11 @@ Sema::BuildExprRequirement(
ExprResult Constraint = SubstExpr(IDC, MLTAL);
if (Constraint.isInvalid()) {
return new (Context) concepts::ExprRequirement(
concepts::createSubstDiagAt(*this, IDC->getExprLoc(),
[&](llvm::raw_ostream &OS) {
IDC->printPretty(OS, /*Helper=*/nullptr,
getPrintingPolicy());
}),
createSubstDiagAt(IDC->getExprLoc(),
[&](llvm::raw_ostream &OS) {
IDC->printPretty(OS, /*Helper=*/nullptr,
getPrintingPolicy());
}),
IsSimple, NoexceptLoc, ReturnTypeRequirement);
}
SubstitutedConstraintExpr =
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18335,7 +18335,8 @@ static bool checkOMPArraySectionConstantForReduction(
return false;

// This is an array subscript which has implicit length 1!
ArraySizes.push_back(llvm::APSInt::get(1));
llvm::APSInt ConstantOne = llvm::APSInt::get(1);
ArraySizes.push_back(ConstantOne);
} else {
Expr::EvalResult Result;
if (!Length->EvaluateAsInt(Result, Context))
Expand All @@ -18354,7 +18355,8 @@ static bool checkOMPArraySectionConstantForReduction(
if (!SingleElement) {
while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
// Has implicit length 1!
ArraySizes.push_back(llvm::APSInt::get(1));
llvm::APSInt ConstantOne = llvm::APSInt::get(1);
ArraySizes.push_back(ConstantOne);
Base = TempASE->getBase()->IgnoreParenImpCasts();
}
}
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2654,7 +2654,7 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(

static concepts::Requirement::SubstitutionDiagnostic *
createSubstDiag(Sema &S, TemplateDeductionInfo &Info,
concepts::EntityPrinter Printer) {
Sema::EntityPrinter Printer) {
SmallString<128> Message;
SourceLocation ErrorLoc;
if (Info.hasSFINAEDiagnostic()) {
Expand All @@ -2675,12 +2675,11 @@ createSubstDiag(Sema &S, TemplateDeductionInfo &Info,
}

concepts::Requirement::SubstitutionDiagnostic *
concepts::createSubstDiagAt(Sema &S, SourceLocation Location,
EntityPrinter Printer) {
Sema::createSubstDiagAt(SourceLocation Location, EntityPrinter Printer) {
SmallString<128> Entity;
llvm::raw_svector_ostream OS(Entity);
Printer(OS);
const ASTContext &C = S.Context;
const ASTContext &C = Context;
return new (C) concepts::Requirement::SubstitutionDiagnostic{
/*SubstitutedEntity=*/C.backupStr(Entity),
/*DiagLoc=*/Location, /*DiagMessage=*/StringRef()};
Expand Down
49 changes: 34 additions & 15 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace {
unsigned DepthLimit = (unsigned)-1;

#ifndef NDEBUG
bool ContainsFunctionParmPackExpr = false;
bool ContainsIntermediatePacks = false;
#endif

void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) {
Expand Down Expand Up @@ -114,6 +114,11 @@ namespace {
addUnexpanded(TTP);
}

#ifndef NDEBUG
ContainsIntermediatePacks |=
(bool)Template.getAsSubstTemplateTemplateParmPack();
#endif

return inherited::TraverseTemplateName(Template);
}

Expand Down Expand Up @@ -297,13 +302,28 @@ namespace {

#ifndef NDEBUG
bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) {
ContainsFunctionParmPackExpr = true;
ContainsIntermediatePacks = true;
return true;
}

bool TraverseSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *) {
ContainsIntermediatePacks = true;
return true;
}

bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *) {
ContainsIntermediatePacks = true;
return true;
}

bool containsFunctionParmPackExpr() const {
return ContainsFunctionParmPackExpr;
bool
VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc) {
ContainsIntermediatePacks = true;
return true;
}

bool containsIntermediatePacks() const { return ContainsIntermediatePacks; }
#endif
};
}
Expand Down Expand Up @@ -439,21 +459,20 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
if (!E->containsUnexpandedParameterPack())
return false;

// FunctionParmPackExprs are special:
//
// 1) they're used to model DeclRefExprs to packs that have been expanded but
// had that expansion held off in the process of transformation.
//
// 2) they always have the unexpanded dependencies but don't introduce new
// unexpanded packs.
//
// We might encounter a FunctionParmPackExpr being a full expression, which a
// larger CXXFoldExpr would expand.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor Visitor(Unexpanded);
Visitor.TraverseStmt(E);
assert((!Unexpanded.empty() || Visitor.containsFunctionParmPackExpr()) &&
#ifndef NDEBUG
// The expression might contain a type/subexpression that has been substituted
// but has the expansion held off, e.g. a FunctionParmPackExpr which a larger
// CXXFoldExpr would expand. It's only possible when expanding a lambda as a
// pattern of a fold expression, so don't fire on an empty result in that
// case.
bool LambdaReferencingOuterPacks =
getEnclosingLambdaOrBlock() && Visitor.containsIntermediatePacks();
assert((!Unexpanded.empty() || LambdaReferencingOuterPacks) &&
"Unable to find unexpanded parameter packs");
#endif
return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded);
}

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3738,12 +3738,12 @@ static CallingConv getCCForDeclaratorChunk(
}
}
} else if (S.getLangOpts().CUDA) {
// If we're compiling CUDA/HIP code and targeting SPIR-V we need to make
// If we're compiling CUDA/HIP code and targeting HIPSPV we need to make
// sure the kernels will be marked with the right calling convention so that
// they will be visible by the APIs that ingest SPIR-V.
// they will be visible by the APIs that ingest SPIR-V. We do not do this
// when targeting AMDGCNSPIRV, as it does not rely on OpenCL.
llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
if (Triple.getArch() == llvm::Triple::spirv32 ||
Triple.getArch() == llvm::Triple::spirv64) {
if (Triple.isSPIRV() && Triple.getVendor() != llvm::Triple::AMD) {
for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
if (AL.getKind() == ParsedAttr::AT_CUDAGlobal) {
CC = CC_OpenCLKernel;
Expand Down
21 changes: 13 additions & 8 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -8385,14 +8385,19 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
if (Transformed != D)
DeclChanged = true;

if (LSI && isa<TypeDecl>(Transformed))
LSI->ContainsUnexpandedParameterPack |=
getSema()
.getASTContext()
.getTypeDeclType(cast<TypeDecl>(Transformed))
.getCanonicalType()
.getTypePtr()
->containsUnexpandedParameterPack();
if (LSI) {
if (auto *TD = dyn_cast<TypeDecl>(Transformed))
LSI->ContainsUnexpandedParameterPack |=
getSema()
.getASTContext()
.getTypeDeclType(TD)
.getCanonicalType()
->containsUnexpandedParameterPack();

if (auto *VD = dyn_cast<VarDecl>(Transformed))
LSI->ContainsUnexpandedParameterPack |=
VD->getType()->containsUnexpandedParameterPack();
}

Decls.push_back(Transformed);
}
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Serialization/ASTCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ModuleFile.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

Expand Down Expand Up @@ -503,3 +506,15 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
return false;
return isa<TagDecl, FieldDecl>(D);
}

void serialization::updateModuleTimestamp(StringRef ModuleFilename) {
// Overwrite the timestamp file contents so that file's mtime changes.
std::error_code EC;
llvm::raw_fd_ostream OS(ModuleFile::getTimestampFilename(ModuleFilename), EC,
llvm::sys::fs::OF_TextWithCRLF);
if (EC)
return;
OS << "Timestamp file\n";
OS.close();
OS.clear_error(); // Avoid triggering a fatal error.
}
3 changes: 3 additions & 0 deletions clang/lib/Serialization/ASTCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/Basic/LLVM.h"
#include "clang/Serialization/ASTBitCodes.h"

namespace clang {
Expand Down Expand Up @@ -100,6 +101,8 @@ inline bool isPartOfPerModuleInitializer(const Decl *D) {
return false;
}

void updateModuleTimestamp(StringRef ModuleFilename);

} // namespace serialization

} // namespace clang
Expand Down
Loading