34 changes: 28 additions & 6 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace clang {
class InMessageExpressionRAIIObject;
class PoisonSEHIdentifiersRAIIObject;
class OMPClause;
class OpenACCClause;
class ObjCTypeParamList;
struct OMPTraitProperty;
struct OMPTraitSelector;
Expand Down Expand Up @@ -3594,11 +3595,26 @@ class Parser : public CodeCompletionHandler {
OpenACCDirectiveKind DirKind;
SourceLocation StartLoc;
SourceLocation EndLoc;
// TODO OpenACC: Add Clause list here once we have a type for that.
SmallVector<OpenACCClause *> Clauses;
// TODO OpenACC: As we implement support for the Atomic, Routine, Cache, and
// Wait constructs, we likely want to put that information in here as well.
};

/// Represents the 'error' state of parsing an OpenACC Clause, and stores
/// whether we can continue parsing, or should give up on the directive.
enum class OpenACCParseCanContinue { Cannot = 0, Can = 1 };

/// A type to represent the state of parsing an OpenACC Clause. Situations
/// that result in an OpenACCClause pointer are a success and can continue
/// parsing, however some other situations can also continue.
/// FIXME: This is better represented as a std::expected when we get C++23.
using OpenACCClauseParseResult =
llvm::PointerIntPair<OpenACCClause *, 1, OpenACCParseCanContinue>;

OpenACCClauseParseResult OpenACCCanContinue();
OpenACCClauseParseResult OpenACCCannotContinue();
OpenACCClauseParseResult OpenACCSuccess(OpenACCClause *Clause);

/// Parses the OpenACC directive (the entire pragma) including the clause
/// list, but does not produce the main AST node.
OpenACCDirectiveParseInfo ParseOpenACCDirective();
Expand All @@ -3613,12 +3629,18 @@ class Parser : public CodeCompletionHandler {
bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
/// Parses any parameters for an OpenACC Clause, including required/optional
/// parens.
bool ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
OpenACCClauseKind Kind);
/// Parses a single clause in a clause-list for OpenACC.
bool ParseOpenACCClause(OpenACCDirectiveKind DirKind);
OpenACCClauseParseResult
ParseOpenACCClauseParams(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind, OpenACCClauseKind Kind,
SourceLocation ClauseLoc);
/// Parses a single clause in a clause-list for OpenACC. Returns nullptr on
/// error.
OpenACCClauseParseResult
ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind);
/// Parses the clause-list for an OpenACC directive.
void ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
SmallVector<OpenACCClause *>
ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
bool ParseOpenACCWaitArgument();
/// Parses the clause of the 'bind' argument, which can be a string literal or
/// an ID expression.
Expand Down
369 changes: 85 additions & 284 deletions clang/include/clang/Sema/Sema.h

Large diffs are not rendered by default.

224 changes: 224 additions & 0 deletions clang/include/clang/Sema/SemaBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
//===--- SemaBase.h - Common utilities for semantic analysis-----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the SemaBase class, which provides utilities for Sema
// and its parts like SemaOpenACC.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMABASE_H
#define LLVM_CLANG_SEMA_SEMABASE_H

#include "clang/AST/Decl.h"
#include "clang/AST/Redeclarable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/DenseMap.h"
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>

namespace clang {

class ASTContext;
class DiagnosticsEngine;
class LangOptions;
class Sema;

class SemaBase {
public:
SemaBase(Sema &S);

Sema &SemaRef;

ASTContext &getASTContext() const;
DiagnosticsEngine &getDiagnostics() const;
const LangOptions &getLangOpts() const;

/// Helper class that creates diagnostics with optional
/// template instantiation stacks.
///
/// This class provides a wrapper around the basic DiagnosticBuilder
/// class that emits diagnostics. ImmediateDiagBuilder is
/// responsible for emitting the diagnostic (as DiagnosticBuilder
/// does) and, if the diagnostic comes from inside a template
/// instantiation, printing the template instantiation stack as
/// well.
class ImmediateDiagBuilder : public DiagnosticBuilder {
Sema &SemaRef;
unsigned DiagID;

public:
ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
: DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}
ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID)
: DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}

// This is a cunning lie. DiagnosticBuilder actually performs move
// construction in its copy constructor (but due to varied uses, it's not
// possible to conveniently express this as actual move construction). So
// the default copy ctor here is fine, because the base class disables the
// source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op
// in that case anwyay.
ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default;

~ImmediateDiagBuilder();

/// Teach operator<< to produce an object of the correct type.
template <typename T>
friend const ImmediateDiagBuilder &
operator<<(const ImmediateDiagBuilder &Diag, const T &Value) {
const DiagnosticBuilder &BaseDiag = Diag;
BaseDiag << Value;
return Diag;
}

// It is necessary to limit this to rvalue reference to avoid calling this
// function with a bitfield lvalue argument since non-const reference to
// bitfield is not allowed.
template <typename T,
typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
const ImmediateDiagBuilder &operator<<(T &&V) const {
const DiagnosticBuilder &BaseDiag = *this;
BaseDiag << std::move(V);
return *this;
}
};

/// A generic diagnostic builder for errors which may or may not be deferred.
///
/// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch)
/// which are not allowed to appear inside __device__ functions and are
/// allowed to appear in __host__ __device__ functions only if the host+device
/// function is never codegen'ed.
///
/// To handle this, we use the notion of "deferred diagnostics", where we
/// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed.
///
/// This class lets you emit either a regular diagnostic, a deferred
/// diagnostic, or no diagnostic at all, according to an argument you pass to
/// its constructor, thus simplifying the process of creating these "maybe
/// deferred" diagnostics.
class SemaDiagnosticBuilder {
public:
enum Kind {
/// Emit no diagnostics.
K_Nop,
/// Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
K_Immediate,
/// Emit the diagnostic immediately, and, if it's a warning or error, also
/// emit a call stack showing how this function can be reached by an a
/// priori known-emitted function.
K_ImmediateWithCallStack,
/// Create a deferred diagnostic, which is emitted only if the function
/// it's attached to is codegen'ed. Also emit a call stack as with
/// K_ImmediateWithCallStack.
K_Deferred
};

SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
const FunctionDecl *Fn, Sema &S);
SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;

// The copy and move assignment operator is defined as deleted pending
// further motivation.
SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;

~SemaDiagnosticBuilder();

bool isImmediate() const { return ImmediateDiag.has_value(); }

/// Convertible to bool: True if we immediately emitted an error, false if
/// we didn't emit an error or we created a deferred error.
///
/// Example usage:
///
/// if (SemaDiagnosticBuilder(...) << foo << bar)
/// return ExprError();
///
/// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably
/// want to use these instead of creating a SemaDiagnosticBuilder yourself.
operator bool() const { return isImmediate(); }

template <typename T>
friend const SemaDiagnosticBuilder &
operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) {
if (Diag.ImmediateDiag)
*Diag.ImmediateDiag << Value;
else if (Diag.PartialDiagId)
Diag.getDeviceDeferredDiags()[Diag.Fn][*Diag.PartialDiagId].second
<< Value;
return Diag;
}

// It is necessary to limit this to rvalue reference to avoid calling this
// function with a bitfield lvalue argument since non-const reference to
// bitfield is not allowed.
template <typename T,
typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
const SemaDiagnosticBuilder &operator<<(T &&V) const {
if (ImmediateDiag)
*ImmediateDiag << std::move(V);
else if (PartialDiagId)
getDeviceDeferredDiags()[Fn][*PartialDiagId].second << std::move(V);
return *this;
}

friend const SemaDiagnosticBuilder &
operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD);

void AddFixItHint(const FixItHint &Hint) const;

friend ExprResult ExprError(const SemaDiagnosticBuilder &) {
return ExprError();
}
friend StmtResult StmtError(const SemaDiagnosticBuilder &) {
return StmtError();
}
operator ExprResult() const { return ExprError(); }
operator StmtResult() const { return StmtError(); }
operator TypeResult() const { return TypeError(); }
operator DeclResult() const { return DeclResult(true); }
operator MemInitResult() const { return MemInitResult(true); }

using DeferredDiagnosticsType =
llvm::DenseMap<CanonicalDeclPtr<const FunctionDecl>,
std::vector<PartialDiagnosticAt>>;

private:
Sema &S;
SourceLocation Loc;
unsigned DiagID;
const FunctionDecl *Fn;
bool ShowCallStack;

// Invariant: At most one of these Optionals has a value.
// FIXME: Switch these to a Variant once that exists.
std::optional<ImmediateDiagBuilder> ImmediateDiag;
std::optional<unsigned> PartialDiagId;

DeferredDiagnosticsType &getDeviceDeferredDiags() const;
};

/// Emit a diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
bool DeferHint = false);

/// Emit a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
bool DeferHint = false);
};

} // namespace clang

#endif
37 changes: 37 additions & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===----- SemaHLSL.h ----- Semantic Analysis for HLSL constructs ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis for HLSL constructs.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAHLSL_H
#define LLVM_CLANG_SEMA_SEMAHLSL_H

#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"

namespace clang {

class SemaHLSL : public SemaBase {
public:
SemaHLSL(Sema &S);

Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
SourceLocation IdentLoc, SourceLocation LBrace);
void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
};

} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAHLSL_H
52 changes: 39 additions & 13 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,49 @@
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class OpenACCClause;

class ASTContext;
class DiagnosticEngine;
class LangOptions;
class Sema;

class SemaOpenACC {
class SemaOpenACC : public SemaBase {
public:
SemaOpenACC(Sema &S);
/// A type to represent all the data for an OpenACC Clause that has been
/// parsed, but not yet created/semantically analyzed. This is effectively a
/// discriminated union on the 'Clause Kind', with all of the individual
/// clause details stored in a std::variant.
class OpenACCParsedClause {
OpenACCDirectiveKind DirKind;
OpenACCClauseKind ClauseKind;
SourceRange ClauseRange;
SourceLocation LParenLoc;

// TODO OpenACC: Add variant here to store details of individual clauses.

public:
OpenACCParsedClause(OpenACCDirectiveKind DirKind,
OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
: DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}

OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }

OpenACCClauseKind getClauseKind() const { return ClauseKind; }

ASTContext &getASTContext() const;
DiagnosticsEngine &getDiagnostics() const;
const LangOptions &getLangOpts() const;
SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }

Sema &SemaRef;
SourceLocation getLParenLoc() const { return LParenLoc; }

SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }

void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
};

SemaOpenACC(Sema &S);

/// Called after parsing an OpenACC Clause so that it can be checked.
bool ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc);
OpenACCClause *ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCParsedClause &Clause);

/// Called after the construct has been parsed, but clauses haven't been
/// parsed. This allows us to diagnose not-implemented, as well as set up any
Expand All @@ -63,7 +86,10 @@ class SemaOpenACC {
/// declaration group or associated statement.
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K,
SourceLocation StartLoc,
SourceLocation EndLoc, StmtResult AssocStmt);
SourceLocation EndLoc,
ArrayRef<OpenACCClause *> Clauses,
StmtResult AssocStmt);

/// Called after the directive has been completely parsed, including the
/// declaration group or associated statement.
DeclGroupRef ActOnEndDeclDirective();
Expand Down
16 changes: 1 addition & 15 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,27 +1089,13 @@ class ASTReader
/// the last time we loaded information about this identifier.
llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration;

class InterestingDecl {
Decl *D;
bool DeclHasPendingBody;

public:
InterestingDecl(Decl *D, bool HasBody)
: D(D), DeclHasPendingBody(HasBody) {}

Decl *getDecl() { return D; }

/// Whether the declaration has a pending body.
bool hasPendingBody() { return DeclHasPendingBody; }
};

/// Contains declarations and definitions that could be
/// "interesting" to the ASTConsumer, when we get that AST consumer.
///
/// "Interesting" declarations are those that have data that may
/// need to be emitted, such as inline function definitions or
/// Objective-C protocols.
std::deque<InterestingDecl> PotentiallyInterestingDecls;
std::deque<Decl *> PotentiallyInterestingDecls;

/// The list of deduced function types that we have not yet read, because
/// they might contain a deduced return type that refers to a local type
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/ADT/APSInt.h"

namespace clang {
class OpenACCClause;
class OMPTraitInfo;
class OMPChildren;

Expand Down Expand Up @@ -278,6 +279,12 @@ class ASTRecordReader
/// Read an OpenMP children, advancing Idx.
void readOMPChildren(OMPChildren *Data);

/// Read an OpenACC clause, advancing Idx.
OpenACCClause *readOpenACCClause();

/// Read a list of OpenACC clauses into the passed SmallVector.
void readOpenACCClauseList(MutableArrayRef<const OpenACCClause *> Clauses);

/// Read a source location, advancing Idx.
SourceLocation readSourceLocation(LocSeq *Seq = nullptr) {
return Reader->ReadSourceLocation(*F, Record, Idx, Seq);
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Serialization/ASTRecordWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

namespace clang {

class OpenACCClause;
class TypeLoc;

/// An object for streaming information to a record.
Expand Down Expand Up @@ -292,6 +293,12 @@ class ASTRecordWriter
/// Writes data related to the OpenMP directives.
void writeOMPChildren(OMPChildren *Data);

/// Writes out a single OpenACC Clause.
void writeOpenACCClause(const OpenACCClause *C);

/// Writes out a list of OpenACC clauses.
void writeOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses);

/// Emit a string.
void AddString(StringRef Str) {
return Writer->AddString(Str, *Record);
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,15 @@ def PthreadLockChecker : Checker<"PthreadLock">,
def StreamChecker : Checker<"Stream">,
HelpText<"Check stream handling functions">,
WeakDependencies<[NonNullParamChecker]>,
CheckerOptions<[
CmdLineOption<Boolean,
"Pedantic",
"If false, assume that stream operations which are often not "
"checked for error do not fail."
"fail.",
"false",
InAlpha>
]>,
Documentation<HasDocumentation>;

def SimpleStreamChecker : Checker<"SimpleStream">,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
/// from.
///
/// \param V We're searching for the store where \c R received this value.
/// It may be either defined or undefined, but should not be unknown.
/// \param R The region we're tracking.
/// \param Opts Tracking options specifying how we want to track the value.
/// \param Origin Only adds notes when the last store happened in a
Expand All @@ -383,7 +384,7 @@ bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
/// changes to its value in a nested stackframe could be pruned, and
/// this visitor can prevent that without polluting the bugpath too
/// much.
void trackStoredValue(KnownSVal V, const MemRegion *R,
void trackStoredValue(SVal V, const MemRegion *R,
PathSensitiveBugReport &Report, TrackingOptions Opts = {},
const StackFrameContext *Origin = nullptr);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@ namespace ento {
class CallDescription {
public:
enum class Mode {
/// Match calls to functions from the C standard library. On some platforms
/// some functions may be implemented as macros that expand to calls to
/// built-in variants of the given functions, so in this mode we use some
/// heuristics to recognize these implementation-defined variants:
/// - We also accept calls where the name is derived from the specified
/// name by adding "__builtin" or similar prefixes/suffixes.
/// - We also accept calls where the number of arguments or parameters is
/// greater than the specified value.
/// Match calls to functions from the C standard library. This also
/// recognizes builtin variants whose name is derived by adding
/// "__builtin", "__inline" or similar prefixes or suffixes; but only
/// matches functions than are externally visible and are declared either
/// directly within a TU or in the namespace 'std'.
/// For the exact heuristics, see CheckerContext::isCLibraryFunction().
/// (This mode only matches functions that are declared either directly
/// within a TU or in the namespace `std`.)
CLibrary,

/// An extended version of the `CLibrary` mode that also matches the
/// hardened variants like __FOO_chk() and __builtin__FOO_chk() that take
/// additional arguments compared to the "regular" function FOO().
/// This is not the default behavior of `CLibrary` because in this case the
/// checker code must be prepared to handle the different parametrization.
/// For the exact heuristics, see CheckerContext::isHardenedVariantOf().
CLibraryMaybeHardened,

/// Matches "simple" functions that are not methods. (Static methods are
/// methods.)
SimpleFunc,
Expand Down Expand Up @@ -187,6 +190,9 @@ class CallDescription {
private:
bool matchesImpl(const FunctionDecl *Callee, size_t ArgCount,
size_t ParamCount) const;

bool matchNameOnly(const NamedDecl *ND) const;
bool matchQualifiedNameParts(const Decl *D) const;
};

/// An immutable map from CallDescriptions to arbitrary data. Provides a unified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,19 +366,31 @@ class CheckerContext {
return getCalleeName(FunDecl);
}

/// Returns true if the callee is an externally-visible function in the
/// top-level namespace, such as \c malloc.
/// Returns true if the given function is an externally-visible function in
/// the top-level namespace, such as \c malloc.
///
/// If a name is provided, the function must additionally match the given
/// name.
///
/// Note that this deliberately excludes C++ library functions in the \c std
/// namespace, but will include C library functions accessed through the
/// \c std namespace. This also does not check if the function is declared
/// as 'extern "C"', or if it uses C++ name mangling.
/// Note that this also accepts functions from the \c std namespace (because
/// headers like <cstdlib> declare them there) and does not check if the
/// function is declared as 'extern "C"' or if it uses C++ name mangling.
static bool isCLibraryFunction(const FunctionDecl *FD,
StringRef Name = StringRef());

/// In builds that use source hardening (-D_FORTIFY_SOURCE), many standard
/// functions are implemented as macros that expand to calls of hardened
/// functions that take additional arguments compared to the "usual"
/// variant and perform additional input validation. For example, a `memcpy`
/// call may expand to `__memcpy_chk()` or `__builtin___memcpy_chk()`.
///
/// This method returns true if `FD` declares a fortified variant of the
/// standard library function `Name`.
///
/// NOTE: This method relies on heuristics; extend it if you need to handle a
/// hardened variant that's not yet covered by it.
static bool isHardenedVariantOf(const FunctionDecl *FD, StringRef Name);

/// Depending on wither the location corresponds to a macro, return
/// either the macro name or the token spelling.
///
Expand Down
8 changes: 0 additions & 8 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,6 @@ class DefinedSVal : public DefinedOrUnknownSVal {
: DefinedOrUnknownSVal(Kind, Data) {}
};

/// Represents an SVal that is guaranteed to not be UnknownVal.
class KnownSVal : public SVal {
public:
/*implicit*/ KnownSVal(DefinedSVal V) : SVal(V) {}
/*implicit*/ KnownSVal(UndefinedVal V) : SVal(V) {}
static bool classof(SVal V) { return !V.isUnknown(); }
};

class NonLoc : public DefinedSVal {
protected:
NonLoc(SValKind Kind, const void *Data) : DefinedSVal(Kind, Data) {}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4541,6 +4541,10 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
ToVar->setQualifierInfo(ToQualifierLoc);
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
if (D->isInlineSpecified())
ToVar->setInlineSpecified();
if (D->isInline())
ToVar->setImplicitlyInline();

if (FoundByLookup) {
auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ add_clang_library(clangAST
NSAPI.cpp
ODRDiagsEmitter.cpp
ODRHash.cpp
OpenACCClause.cpp
OpenMPClause.cpp
OSLog.cpp
ParentMap.cpp
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ ExprDependence clang::computeDependence(CXXThisExpr *E) {
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());

// If a lambda with an explicit object parameter captures '*this', then
// 'this' now refers to the captured copy of lambda, and if the lambda
// is type-dependent, so is the object and thus 'this'.
//
// Note: The standard does not mention this case explicitly, but we need
// to do this so we can mark NSDM accesses as dependent.
if (E->isCapturedByCopyInLambdaWithExplicitObjectParameter())
D |= ExprDependence::Type;

assert(!(D & ExprDependence::UnexpandedPack));
return D;
}
Expand Down
179 changes: 47 additions & 132 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

Expand Down Expand Up @@ -49,18 +50,6 @@ namespace {

void PrintObjCTypeParams(ObjCTypeParamList *Params);

enum class AttrPrintLoc {
None = 0,
Left = 1,
Right = 2,
Any = Left | Right,

LLVM_MARK_AS_BITMASK_ENUM(/*DefaultValue=*/Any)
};

void prettyPrintAttributes(Decl *D, raw_ostream &out,
AttrPrintLoc loc = AttrPrintLoc::Any);

public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
const ASTContext &Context, unsigned Indentation = 0,
Expand Down Expand Up @@ -129,11 +118,10 @@ namespace {
const TemplateParameterList *Params);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);

inline void prettyPrintAttributes(Decl *D) {
prettyPrintAttributes(D, Out);
}

enum class AttrPosAsWritten { Default = 0, Left, Right };
void
prettyPrintAttributes(const Decl *D,
AttrPosAsWritten Pos = AttrPosAsWritten::Default);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
Expand Down Expand Up @@ -250,87 +238,48 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}

// For CLANG_ATTR_LIST_CanPrintOnLeft macro.
#include "clang/Basic/AttrLeftSideCanPrintList.inc"
static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
const Decl *D) {
SourceLocation ALoc = A->getLoc();
SourceLocation DLoc = D->getLocation();
const ASTContext &C = D->getASTContext();
if (ALoc.isInvalid() || DLoc.isInvalid())
return DeclPrinter::AttrPosAsWritten::Left;

// For CLANG_ATTR_LIST_PrintOnLeft macro.
#include "clang/Basic/AttrLeftSideMustPrintList.inc"
if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))
return DeclPrinter::AttrPosAsWritten::Left;

static bool canPrintOnLeftSide(attr::Kind kind) {
#ifdef CLANG_ATTR_LIST_CanPrintOnLeft
switch (kind) {
CLANG_ATTR_LIST_CanPrintOnLeft
return true;
default:
return false;
}
#else
return false;
#endif
}

static bool canPrintOnLeftSide(const Attr *A) {
if (A->isStandardAttributeSyntax())
return false;

return canPrintOnLeftSide(A->getKind());
return DeclPrinter::AttrPosAsWritten::Right;
}

static bool mustPrintOnLeftSide(attr::Kind kind) {
#ifdef CLANG_ATTR_LIST_PrintOnLeft
switch (kind) {
CLANG_ATTR_LIST_PrintOnLeft
return true;
default:
return false;
}
#else
return false;
#endif
}

static bool mustPrintOnLeftSide(const Attr *A) {
if (A->isDeclspecAttribute())
return true;

return mustPrintOnLeftSide(A->getKind());
}

void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
AttrPrintLoc Loc) {
void DeclPrinter::prettyPrintAttributes(const Decl *D,
AttrPosAsWritten Pos /*=Default*/) {
if (Policy.PolishForDeclaration)
return;

if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
const AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
continue;

AttrPrintLoc AttrLoc = AttrPrintLoc::Right;
if (mustPrintOnLeftSide(A)) {
// If we must always print on left side (e.g. declspec), then mark as
// so.
AttrLoc = AttrPrintLoc::Left;
} else if (canPrintOnLeftSide(A)) {
// For functions with body defined we print the attributes on the left
// side so that GCC accept our dumps as well.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
FD && FD->isThisDeclarationADefinition())
// In case Decl is a function with a body, then attrs should be print
// on the left side.
AttrLoc = AttrPrintLoc::Left;

// In case it is a variable declaration with a ctor, then allow
// printing on the left side for readbility.
else if (const VarDecl *VD = dyn_cast<VarDecl>(D);
VD && VD->getInit() &&
VD->getInitStyle() == VarDecl::CallInit)
AttrLoc = AttrPrintLoc::Left;
switch (A->getKind()) {
#define ATTR(X)
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
#include "clang/Basic/AttrList.inc"
break;
default:
AttrPosAsWritten APos = getPosAsWritten(A, D);
assert(APos != AttrPosAsWritten::Default &&
"Default not a valid for an attribute location");
if (Pos == AttrPosAsWritten::Default || Pos == APos) {
if (Pos != AttrPosAsWritten::Left)
Out << ' ';
A->printPretty(Out, Policy);
if (Pos == AttrPosAsWritten::Left)
Out << ' ';
}
break;
}
// Only print the side matches the user requested.
if ((Loc & AttrLoc) != AttrPrintLoc::None)
A->printPretty(Out, Policy);
}
}
}
Expand Down Expand Up @@ -691,8 +640,10 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,

void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
!D->isFunctionTemplateSpecialization())
!D->isFunctionTemplateSpecialization()) {
prettyPrintPragmas(D);
prettyPrintAttributes(D, AttrPosAsWritten::Left);
}

if (D->isFunctionTemplateSpecialization())
Out << "template<> ";
Expand All @@ -702,22 +653,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
printTemplateParameters(D->getTemplateParameterList(I));
}

std::string LeftsideAttrs;
llvm::raw_string_ostream LSAS(LeftsideAttrs);

prettyPrintAttributes(D, LSAS, AttrPrintLoc::Left);

// prettyPrintAttributes print a space on left side of the attribute.
if (LeftsideAttrs[0] == ' ') {
// Skip the space prettyPrintAttributes generated.
LeftsideAttrs.erase(0, LeftsideAttrs.find_first_not_of(' '));

// Add a single space between the attribute and the Decl name.
LSAS << ' ';
}

Out << LeftsideAttrs;

CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
Expand Down Expand Up @@ -883,7 +818,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Ty.print(Out, Policy, Proto);
}

prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
prettyPrintAttributes(D, AttrPosAsWritten::Right);

if (D->isPureVirtual())
Out << " = 0";
Expand Down Expand Up @@ -976,27 +911,12 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
void DeclPrinter::VisitVarDecl(VarDecl *D) {
prettyPrintPragmas(D);

prettyPrintAttributes(D, AttrPosAsWritten::Left);

if (const auto *Param = dyn_cast<ParmVarDecl>(D);
Param && Param->isExplicitObjectParameter())
Out << "this ";

std::string LeftSide;
llvm::raw_string_ostream LeftSideStream(LeftSide);

// Print attributes that should be placed on the left, such as __declspec.
prettyPrintAttributes(D, LeftSideStream, AttrPrintLoc::Left);

// prettyPrintAttributes print a space on left side of the attribute.
if (LeftSide[0] == ' ') {
// Skip the space prettyPrintAttributes generated.
LeftSide.erase(0, LeftSide.find_first_not_of(' '));

// Add a single space between the attribute and the Decl name.
LeftSideStream << ' ';
}

Out << LeftSide;

QualType T = D->getTypeSourceInfo()
? D->getTypeSourceInfo()->getType()
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
Expand Down Expand Up @@ -1029,21 +949,16 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
}
}

StringRef Name;

Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
D->getIdentifier())
? D->getIdentifier()->deuglifiedName()
: D->getName();

if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope)
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
printDeclType(T, Name);

// Print the attributes that should be placed right before the end of the
// decl.
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
D->getIdentifier())
? D->getIdentifier()->deuglifiedName()
: D->getName());

prettyPrintAttributes(D, AttrPosAsWritten::Right);

Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,9 @@ static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
if (const auto *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();

if (T.getQualifiers().hasUnaligned())
return CharUnits::One();

// __alignof is defined to return the preferred alignment.
// Before 8, clang returned the preferred alignment for alignof and
// _Alignof as well.
Expand Down Expand Up @@ -2511,6 +2514,7 @@ unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
assert(!P.getGlobal(VD));
assert(!Locals.contains(VD));
(void)VD;
}

// FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
Expand Down
31 changes: 31 additions & 0 deletions clang/lib/AST/Interp/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,34 @@ LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
F = F->Caller;
}
}

LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
unsigned Offset) const {
unsigned Indent = Indentation * 2;
OS.indent(Indent);
{
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
OS << getName() << "\n";
}

unsigned I = 0;
for (const Record::Base &B : bases()) {
OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
<< "\n";
B.R->dump(OS, Indentation + 1, Offset + B.Offset);
++I;
}

// FIXME: Virtual bases.

I = 0;
for (const Record::Field &F : fields()) {
OS.indent(Indent) << "- Field " << I << ": ";
{
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
OS << F.Decl->getName();
}
OS << ". Offset " << (Offset + F.Offset) << "\n";
++I;
}
}
26 changes: 26 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,18 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
return true;
}

for (const auto &P : {LHS, RHS}) {
if (P.isZero())
continue;
if (const ValueDecl *VD = P.getDeclDesc()->asValueDecl();
VD && VD->isWeak()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
<< P.toDiagnosticString(S.getCtx());
return false;
}
}

if (!Pointer::hasSameBase(LHS, RHS)) {
S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
return true;
Expand Down Expand Up @@ -1333,6 +1345,11 @@ inline bool FinishInit(InterpState &S, CodePtr OpPC) {
return true;
}

inline bool Dump(InterpState &S, CodePtr OpPC) {
S.Stk.dump();
return true;
}

inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
const Pointer &Ptr) {
Pointer Base = Ptr;
Expand Down Expand Up @@ -1841,6 +1858,15 @@ inline bool This(InterpState &S, CodePtr OpPC) {
if (!CheckThis(S, OpPC, This))
return false;

// Ensure the This pointer has been cast to the correct base.
if (!This.isDummy()) {
assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
assert(This.getRecord());
assert(
This.getRecord()->getDecl() ==
cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
}

S.Stk.push<Pointer>(This);
return true;
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -723,3 +723,8 @@ def CheckNonNullArg : Opcode {
}

def Memcpy : Opcode;

//===----------------------------------------------------------------------===//
// Debugging.
//===----------------------------------------------------------------------===//
def Dump : Opcode;
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ void Pointer::initialize() const {
if (isStatic() && Base == 0)
return;

// Nothing to do for these.
if (Desc->getNumElems() == 0)
return;

InitMapPtr &IM = getInitMap();
if (!IM)
IM =
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/Interp/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "Record.h"
#include "clang/AST/ASTContext.h"

using namespace clang;
using namespace clang::interp;
Expand All @@ -27,6 +28,14 @@ Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
VirtualBaseMap[V.Decl] = &V;
}

const std::string Record::getName() const {
std::string Ret;
llvm::raw_string_ostream OS(Ret);
Decl->getNameForDiagnostic(OS, Decl->getASTContext().getPrintingPolicy(),
/*Qualified=*/true);
return Ret;
}

const Record::Field *Record::getField(const FieldDecl *FD) const {
auto It = FieldMap.find(FD);
assert(It != FieldMap.end() && "Missing field");
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/Interp/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Record final {
/// Returns the underlying declaration.
const RecordDecl *getDecl() const { return Decl; }
/// Returns the name of the underlying declaration.
const std::string getName() const { return Decl->getNameAsString(); }
const std::string getName() const;
/// Checks if the record is a union.
bool isUnion() const { return getDecl()->isUnion(); }
/// Returns the size of the record.
Expand Down Expand Up @@ -100,6 +100,10 @@ class Record final {
unsigned getNumVirtualBases() const { return VirtualBases.size(); }
const Base *getVirtualBase(unsigned I) const { return &VirtualBases[I]; }

void dump(llvm::raw_ostream &OS, unsigned Indentation = 0,
unsigned Offset = 0) const;
void dump() const { dump(llvm::errs()); }

private:
/// Constructor used by Program to create record descriptors.
Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
llvm_unreachable("Unknown initializer type");
}

void JSONNodeDumper::Visit(const OpenACCClause *C) {}

void JSONNodeDumper::Visit(const OMPClause *C) {}

void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===---- OpenACCClause.cpp - Classes for OpenACC Clauses ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the subclasses of the OpenACCClause class declared in
// OpenACCClause.h
//
//===----------------------------------------------------------------------===//

#include "clang/AST/OpenACCClause.h"
#include "clang/AST/ASTContext.h"

using namespace clang;
19 changes: 11 additions & 8 deletions clang/lib/AST/StmtOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@
using namespace clang;

OpenACCComputeConstruct *
OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, EmptyShell) {
void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
alignof(OpenACCComputeConstruct));
auto *Inst = new (Mem) OpenACCComputeConstruct;
OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
void *Mem = C.Allocate(
OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
NumClauses));
auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses);
return Inst;
}

OpenACCComputeConstruct *
OpenACCComputeConstruct::Create(const ASTContext &C, OpenACCDirectiveKind K,
SourceLocation BeginLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses,
Stmt *StructuredBlock) {
void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
alignof(OpenACCComputeConstruct));
auto *Inst =
new (Mem) OpenACCComputeConstruct(K, BeginLoc, EndLoc, StructuredBlock);
void *Mem = C.Allocate(
OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
Clauses.size()));
auto *Inst = new (Mem)
OpenACCComputeConstruct(K, BeginLoc, EndLoc, Clauses, StructuredBlock);
return Inst;
}
13 changes: 11 additions & 2 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,11 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
}

void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
for (const auto *Attr : Node->getAttrs()) {
llvm::ArrayRef<const Attr *> Attrs = Node->getAttrs();
for (const auto *Attr : Attrs) {
Attr->printPretty(OS, Policy);
if (Attr != Attrs.back())
OS << ' ';
}

PrintStmt(Node->getSubStmt(), 0);
Expand Down Expand Up @@ -1142,7 +1145,13 @@ void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective(
//===----------------------------------------------------------------------===//
void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
Indent() << "#pragma acc " << S->getDirectiveKind();
// TODO OpenACC: Print Clauses.

if (!S->clauses().empty()) {
OS << ' ';
OpenACCClausePrinter Printer(OS);
Printer.VisitClauseList(S->clauses());
}

PrintStmt(S->getStructuredBlock());
}

Expand Down
22 changes: 21 additions & 1 deletion clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,7 @@ void StmtProfiler::VisitMSPropertySubscriptExpr(
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isImplicit());
ID.AddBoolean(S->isCapturedByCopyInLambdaWithExplicitObjectParameter());
}

void StmtProfiler::VisitCXXThrowExpr(const CXXThrowExpr *S) {
Expand Down Expand Up @@ -2441,11 +2442,30 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
}
}

namespace {
class OpenACCClauseProfiler
: public OpenACCClauseVisitor<OpenACCClauseProfiler> {

public:
OpenACCClauseProfiler() = default;

void VisitOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses) {
for (const OpenACCClause *Clause : Clauses) {
// TODO OpenACC: When we have clauses with expressions, we should
// profile them too.
Visit(Clause);
}
}
};
} // namespace

void StmtProfiler::VisitOpenACCComputeConstruct(
const OpenACCComputeConstruct *S) {
// VisitStmt handles children, so the AssociatedStmt is handled.
VisitStmt(S);
// TODO OpenACC: Visit Clauses.

OpenACCClauseProfiler P;
P.VisitOpenACCClauseList(S->clauses());
}

void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expand Down
22 changes: 20 additions & 2 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,20 @@ void TextNodeDumper::Visit(const OMPClause *C) {
OS << " <implicit>";
}

void TextNodeDumper::Visit(const OpenACCClause *C) {
if (!C) {
ColorScope Color(OS, ShowColors, NullColor);
OS << "<<<NULL>>> OpenACCClause";
return;
}
{
ColorScope Color(OS, ShowColors, AttrColor);
OS << C->getClauseKind();
}
dumpPointer(C);
dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
}

void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
const TypeSourceInfo *TSI = A.getTypeSourceInfo();
if (TSI) {
Expand Down Expand Up @@ -1180,8 +1194,11 @@ void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
case NOUR_Constant: OS << " non_odr_use_constant"; break;
case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
}
if (Node->refersToEnclosingVariableOrCapture())
if (Node->isCapturedByCopyInLambdaWithExplicitObjectParameter())
OS << " dependent_capture";
else if (Node->refersToEnclosingVariableOrCapture())
OS << " refers_to_enclosing_variable_or_capture";

if (Node->isImmediateEscalating())
OS << " immediate-escalating";
}
Expand Down Expand Up @@ -1337,6 +1354,8 @@ void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
if (Node->isImplicit())
OS << " implicit";
if (Node->isCapturedByCopyInLambdaWithExplicitObjectParameter())
OS << " dependent_capture";
OS << " this";
}

Expand Down Expand Up @@ -2684,5 +2703,4 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {

void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
// TODO OpenACC: Dump clauses as well.
}
1 change: 1 addition & 0 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,7 @@ void Environment::setValue(const Expr &E, Value &Val) {
if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
assert(isOriginalRecordConstructor(CanonE) ||
&RecordVal->getLoc() == &getResultObjectLocation(CanonE));
(void)RecordVal;
}

assert(CanonE.isPRValue());
Expand Down
12 changes: 3 additions & 9 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,17 @@
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/KCFI.h"
#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h"
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
Expand Down Expand Up @@ -747,18 +746,13 @@ static void addSanitizers(const Triple &TargetTriple,
PB.registerOptimizerLastEPCallback(SanitizersCallback);
}

if (RemoveTrapsPass::IsRequested()) {
if (LowerAllowCheckPass::IsRequested()) {
// We can optimize after inliner, and PGO profile matching. The hook below
// is called at the end `buildFunctionSimplificationPipeline`, which called
// from `buildInlinerPipeline`, which called after profile matching.
PB.registerScalarOptimizerLateEPCallback(
[](FunctionPassManager &FPM, OptimizationLevel Level) {
// RemoveTrapsPass expects trap blocks preceded by conditional
// branches, which usually is not the case without SimplifyCFG.
// TODO: Remove `SimplifyCFGPass` after switching to dedicated
// intrinsic.
FPM.addPass(SimplifyCFGPass());
FPM.addPass(RemoveTrapsPass());
FPM.addPass(LowerAllowCheckPass());
});
}
}
Expand Down
25 changes: 20 additions & 5 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ABIInfo.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGHLSLRuntime.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
#include "CGRecordLayout.h"
Expand Down Expand Up @@ -3439,12 +3440,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
StringRef Kind =
cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts())->getString();
LLVMContext &Ctx = CGM.getLLVMContext();
llvm::Metadata *KindStr[] = {llvm::MDString::get(Ctx, Kind)};
llvm::MDNode *KindNode = llvm::MDNode::get(Ctx, KindStr);
llvm::Value *KindMD = llvm::MetadataAsValue::get(Ctx, KindNode);
llvm::Value *Allow = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::allow_runtime_check), KindMD);

CGM.getIntrinsic(llvm::Intrinsic::allow_runtime_check),
llvm::MetadataAsValue::get(Ctx, llvm::MDString::get(Ctx, Kind)));
return RValue::get(Allow);
}
case Builtin::BI__arithmetic_fence: {
Expand Down Expand Up @@ -17299,6 +17297,16 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
Value *Op3 = EmitScalarExpr(E->getArg(3));
// rldimi is 64-bit instruction, expand the intrinsic before isel to
// leverage peephole and avoid legalization efforts.
if (BuiltinID == PPC::BI__builtin_ppc_rldimi &&
!getTarget().getTriple().isPPC64()) {
Function *F = CGM.getIntrinsic(Intrinsic::fshl, Op0->getType());
Op2 = Builder.CreateZExt(Op2, Int64Ty);
Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});
return Builder.CreateOr(Builder.CreateAnd(Shift, Op3),
Builder.CreateAnd(Op1, Builder.CreateNot(Op3)));
}
return Builder.CreateCall(
CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi
? Intrinsic::ppc_rldimi
Expand Down Expand Up @@ -18184,6 +18192,13 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
return nullptr;

switch (BuiltinID) {
case Builtin::BI__builtin_hlsl_elementwise_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
/*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
"hlsl.all");
}
case Builtin::BI__builtin_hlsl_elementwise_any: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,7 +1404,7 @@ FieldHasTrivialDestructorBody(ASTContext &Context,

// The destructor for an implicit anonymous union member is never invoked.
if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
return false;
return true;

return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
}
Expand Down
37 changes: 35 additions & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5597,11 +5597,44 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
break;
}

RValue RV = EmitAnyExpr(E->getRHS());
// TODO: Can we de-duplicate this code with the corresponding code in
// CGExprScalar, similar to the way EmitCompoundAssignmentLValue works?
RValue RV;
llvm::Value *Previous = nullptr;
QualType SrcType = E->getRHS()->getType();
// Check if LHS is a bitfield, if RHS contains an implicit cast expression
// we want to extract that value and potentially (if the bitfield sanitizer
// is enabled) use it to check for an implicit conversion.
if (E->getLHS()->refersToBitField()) {
llvm::Value *RHS =
EmitWithOriginalRHSBitfieldAssignment(E, &Previous, &SrcType);
RV = RValue::get(RHS);
} else
RV = EmitAnyExpr(E->getRHS());

LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);

if (RV.isScalar())
EmitNullabilityCheck(LV, RV.getScalarVal(), E->getExprLoc());
EmitStoreThroughLValue(RV, LV);

if (LV.isBitField()) {
llvm::Value *Result = nullptr;
// If bitfield sanitizers are enabled we want to use the result
// to check whether a truncation or sign change has occurred.
if (SanOpts.has(SanitizerKind::ImplicitBitfieldConversion))
EmitStoreThroughBitfieldLValue(RV, LV, &Result);
else
EmitStoreThroughBitfieldLValue(RV, LV);

// If the expression contained an implicit conversion, make sure
// to use the value before the scalar conversion.
llvm::Value *Src = Previous ? Previous : RV.getScalarVal();
QualType DstType = E->getLHS()->getType();
EmitBitfieldConversionCheck(Src, SrcType, Result, DstType,
LV.getBitFieldInfo(), E->getExprLoc());
} else
EmitStoreThroughLValue(RV, LV);

if (getLangOpts().OpenMP)
CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
E->getLHS());
Expand Down
264 changes: 230 additions & 34 deletions clang/lib/CodeGen/CGExprScalar.cpp

Large diffs are not rendered by default.

20 changes: 6 additions & 14 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FormatVariadic.h"
Expand Down Expand Up @@ -117,6 +115,10 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {

} // namespace

llvm::Triple::ArchType CGHLSLRuntime::getArch() {
return CGM.getTarget().getTriple().getArch();
}

void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) {
if (D->getStorageClass() == SC_Static) {
// For static inside cbuffer, take as global static.
Expand Down Expand Up @@ -343,18 +345,8 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
return B.CreateCall(FunctionCallee(DxGroupIndex));
}
if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
llvm::Function *ThreadIDIntrinsic;
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::dx_thread_id);
break;
case llvm::Triple::spirv:
ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::spv_thread_id);
break;
default:
llvm_unreachable("Input semantic not supported by target");
break;
}
llvm::Function *ThreadIDIntrinsic =
CGM.getIntrinsic(getThreadIdIntrinsic());
return buildVectorInput(B, ThreadIDIntrinsic, Ty);
}
assert(false && "Unhandled parameter attribute");
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
#define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H

#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/IntrinsicsSPIRV.h"

#include "clang/Basic/Builtins.h"
#include "clang/Basic/HLSLRuntime.h"

#include "llvm/ADT/SmallVector.h"
Expand All @@ -26,6 +30,22 @@
#include <optional>
#include <vector>

// A function generator macro for picking the right intrinsic
// for the target backend
#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \
llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \
llvm::Triple::ArchType Arch = getArch(); \
switch (Arch) { \
case llvm::Triple::dxil: \
return llvm::Intrinsic::dx_##IntrinsicPostfix; \
case llvm::Triple::spirv: \
return llvm::Intrinsic::spv_##IntrinsicPostfix; \
default: \
llvm_unreachable("Intrinsic " #IntrinsicPostfix \
" not supported by target architecture"); \
} \
}

namespace llvm {
class GlobalVariable;
class Function;
Expand All @@ -48,6 +68,17 @@ class CodeGenModule;

class CGHLSLRuntime {
public:
//===----------------------------------------------------------------------===//
// Start of reserved area for HLSL intrinsic getters.
//===----------------------------------------------------------------------===//

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
//===----------------------------------------------------------------------===//

struct BufferResBinding {
// The ID like 2 in register(b2, space1).
std::optional<unsigned> Reg;
Expand Down Expand Up @@ -96,6 +127,7 @@ class CGHLSLRuntime {
BufferResBinding &Binding);
void addConstant(VarDecl *D, Buffer &CB);
void addBufferDecls(const DeclContext *DC, Buffer &CB);
llvm::Triple::ArchType getArch();
llvm::SmallVector<Buffer> Buffers;
};

Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2786,6 +2786,21 @@ class CodeGenFunction : public CodeGenTypeCache {
/// expression and compare the result against zero, returning an Int1Ty value.
llvm::Value *EvaluateExprAsBool(const Expr *E);

/// Retrieve the implicit cast expression of the rhs in a binary operator
/// expression by passing pointers to Value and QualType
/// This is used for implicit bitfield conversion checks, which
/// must compare with the value before potential truncation.
llvm::Value *EmitWithOriginalRHSBitfieldAssignment(const BinaryOperator *E,
llvm::Value **Previous,
QualType *SrcType);

/// Emit a check that an [implicit] conversion of a bitfield. It is not UB,
/// so we use the value after conversion.
void EmitBitfieldConversionCheck(llvm::Value *Src, QualType SrcType,
llvm::Value *Dst, QualType DstType,
const CGBitFieldInfo &Info,
SourceLocation Loc);

/// EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitIgnoredExpr(const Expr *E);

Expand Down
32 changes: 21 additions & 11 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
Expand Down Expand Up @@ -97,8 +98,6 @@ static bool TypeHasMayAlias(QualType QTy) {

/// Check if the given type is a valid base type to be used in access tags.
static bool isValidBaseType(QualType QTy) {
if (QTy->isReferenceType())
return false;
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
// Incomplete types are not valid base access types.
Expand Down Expand Up @@ -242,9 +241,10 @@ llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
// aggregate will result into the may-alias access descriptor, meaning all
// subsequent accesses to direct and indirect members of that aggregate will
// be considered may-alias too.
// TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function.
// TODO: Combine getTypeInfo() and getValidBaseTypeInfo() into a single
// function.
if (isValidBaseType(QTy))
return getBaseTypeInfo(QTy);
return getValidBaseTypeInfo(QTy);

const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
if (llvm::MDNode *N = MetadataCache[Ty])
Expand Down Expand Up @@ -319,7 +319,13 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
// base type.
if ((*i)->isBitField()) {
const CGBitFieldInfo &Info = CGRL.getBitFieldInfo(*i);
if (Info.Offset != 0)
// For big endian targets the first bitfield in the consecutive run is
// at the most-significant end; see CGRecordLowering::setBitFieldInfo
// for more information.
bool IsBE = Context.getTargetInfo().isBigEndian();
bool IsFirst = IsBE ? Info.StorageSize - (Info.Offset + Info.Size) == 0
: Info.Offset == 0;
if (!IsFirst)
continue;
unsigned CurrentBitFieldSize = Info.StorageSize;
uint64_t Size =
Expand Down Expand Up @@ -387,7 +393,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
if (BaseRD->isEmpty())
continue;
llvm::MDNode *TypeNode = isValidBaseType(BaseQTy)
? getBaseTypeInfo(BaseQTy)
? getValidBaseTypeInfo(BaseQTy)
: getTypeInfo(BaseQTy);
if (!TypeNode)
return nullptr;
Expand All @@ -411,8 +417,9 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
if (Field->isZeroSize(Context) || Field->isUnnamedBitfield())
continue;
QualType FieldQTy = Field->getType();
llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
llvm::MDNode *TypeNode = isValidBaseType(FieldQTy)
? getValidBaseTypeInfo(FieldQTy)
: getTypeInfo(FieldQTy);
if (!TypeNode)
return nullptr;

Expand Down Expand Up @@ -449,9 +456,8 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
return nullptr;
}

llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
if (!isValidBaseType(QTy))
return nullptr;
llvm::MDNode *CodeGenTBAA::getValidBaseTypeInfo(QualType QTy) {
assert(isValidBaseType(QTy) && "Must be a valid base type");

const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();

Expand All @@ -470,6 +476,10 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
return TypeNode;
}

llvm::MDNode *CodeGenTBAA::getBaseTypeInfo(QualType QTy) {
return isValidBaseType(QTy) ? getValidBaseTypeInfo(QTy) : nullptr;
}

llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
assert(!Info.isIncomplete() && "Access to an object of an incomplete type!");

Expand Down
9 changes: 7 additions & 2 deletions clang/lib/CodeGen/CodeGenTBAA.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ class CodeGenTBAA {
/// used to describe accesses to objects of the given base type.
llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty);

/// getValidBaseTypeInfo - Return metadata that describes the given base
/// access type. The type must be suitable.
llvm::MDNode *getValidBaseTypeInfo(QualType QTy);

public:
CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M,
const CodeGenOptions &CGO, const LangOptions &Features,
Expand All @@ -190,8 +194,9 @@ class CodeGenTBAA {
/// the given type.
llvm::MDNode *getTBAAStructInfo(QualType QTy);

/// getBaseTypeInfo - Get metadata that describes the given base access type.
/// Return null if the type is not suitable for use in TBAA access tags.
/// getBaseTypeInfo - Get metadata that describes the given base access
/// type. Return null if the type is not suitable for use in TBAA access
/// tags.
llvm::MDNode *getBaseTypeInfo(QualType QTy);

/// getAccessTagInfo - Get TBAA tag for a given memory access.
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,12 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
// Print out the install directory.
OS << "InstalledDir: " << Dir << '\n';

// Print the build config if it's non-default.
// Intended to help LLVM developers understand the configs of compilers
// they're investigating.
if (!llvm::cl::getCompilerBuildConfig().empty())
llvm::cl::printBuildConfig(OS);

// If configuration files were used, print their paths.
for (auto ConfigFile : ConfigFiles)
OS << "Configuration file: " << ConfigFile << '\n';
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,13 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
std::optional<std::string> ToolChain::getRuntimePath() const {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "lib");
return getTargetSubDirPath(P);
if (auto Ret = getTargetSubDirPath(P))
return Ret;
// Darwin does not use per-target runtime directory.
if (Triple.isOSDarwin())
return {};
llvm::sys::path::append(P, Triple.str());
return std::string(P);
}

std::optional<std::string> ToolChain::getStdlibPath() const {
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"

#include <set>

using AIX = clang::driver::toolchains::AIX;
using namespace clang::driver;
using namespace clang::driver::tools;
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,6 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
if (Args.hasArg(options::OPT_ffixed_x28))
Features.push_back("+reserve-x28");

if (Args.hasArg(options::OPT_ffixed_x30))
Features.push_back("+reserve-x30");

if (Args.hasArg(options::OPT_fcall_saved_x8))
Features.push_back("+call-saved-x8");

Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,10 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
}

for (Arg *A : Args) {
DAL->append(A);
// Make sure flags are not duplicated.
if (!llvm::is_contained(*DAL, A)) {
DAL->append(A);
}
}

if (!BoundArch.empty()) {
Expand Down
62 changes: 41 additions & 21 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,18 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,

void Flang::addFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,
options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ,
options::OPT_fopenmp,
options::OPT_fopenmp_version_EQ,
options::OPT_fopenacc,
options::OPT_finput_charset_EQ,
options::OPT_fimplicit_none,
options::OPT_fno_implicit_none,
options::OPT_fbackslash,
options::OPT_fno_backslash,
options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator,
options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8,
options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8,
options::OPT_flarge_sizes,
options::OPT_fno_automatic});
Args.addAllArgs(
CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ, options::OPT_fopenacc,
options::OPT_finput_charset_EQ, options::OPT_fimplicit_none,
options::OPT_fno_implicit_none, options::OPT_fbackslash,
options::OPT_fno_backslash, options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator, options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
options::OPT_fno_automatic});
}

void Flang::addPreprocessingOptions(const ArgList &Args,
Expand Down Expand Up @@ -763,6 +754,35 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
// Add other compile options
addOtherOptions(Args, CmdArgs);

// Forward flags for OpenMP. We don't do this if the current action is an
// device offloading action other than OpenMP.
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false) &&
(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_OpenMP))) {
switch (D.getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
case Driver::OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
CmdArgs.push_back("-fopenmp");
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);

// FIXME: Clang supports a whole bunch more flags here.
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
// for a specific runtime library, we just don't pass the '-fopenmp' flag
// down to the actual compilation.
// FIXME: It would be better to have a mode which *only* omits IR
// generation based on the OpenMP support so that we get consistent
// semantic analysis, etc.
const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
D.Diag(diag::warn_drv_unsupported_openmp_library)
<< A->getSpelling() << A->getValue();
break;
}
}

// Offloading related options
addOffloadOptions(C, Inputs, JA, Args, CmdArgs);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ bool FormatTokenLexer::tryMergeNullishCoalescingEqual() {
return false;
auto &NullishCoalescing = *(Tokens.end() - 2);
auto &Equal = *(Tokens.end() - 1);
if (NullishCoalescing->getType() != TT_NullCoalescingOperator ||
if (NullishCoalescing->isNot(TT_NullCoalescingOperator) ||
Equal->isNot(tok::equal)) {
return false;
}
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Format/FormatTokenSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ class FormatTokenSource {
// getNextToken() -> a1
// getNextToken() -> a2
virtual FormatToken *insertTokens(ArrayRef<FormatToken *> Tokens) = 0;

[[nodiscard]] FormatToken *getNextNonComment() {
FormatToken *Tok;
do {
Tok = getNextToken();
assert(Tok);
} while (Tok->is(tok::comment));
return Tok;
}
};

class IndexedTokenSource : public FormatTokenSource {
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,7 @@ class AnnotatingParser {
Parent->overwriteFixedType(TT_BinaryOperator);
}
// An arrow after an ObjC method expression is not a lambda arrow.
if (CurrentToken->getType() == TT_ObjCMethodExpr &&
CurrentToken->Next &&
if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
CurrentToken->Next->is(TT_TrailingReturnArrow)) {
CurrentToken->Next->overwriteFixedType(TT_Unknown);
}
Expand Down Expand Up @@ -1563,7 +1562,7 @@ class AnnotatingParser {
case tok::l_brace:
if (Style.Language == FormatStyle::LK_TextProto) {
FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->getType() != TT_DictLiteral)
if (Previous && Previous->isNot(TT_DictLiteral))
Previous->setType(TT_SelectorName);
}
Scopes.push_back(getScopeType(*Tok));
Expand All @@ -1583,7 +1582,7 @@ class AnnotatingParser {
Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
Tok->setType(TT_DictLiteral);
FormatToken *Previous = Tok->getPreviousNonComment();
if (Previous && Previous->getType() != TT_DictLiteral)
if (Previous && Previous->isNot(TT_DictLiteral))
Previous->setType(TT_SelectorName);
}
if (Style.isTableGen())
Expand Down Expand Up @@ -4754,8 +4753,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// Objective-C dictionary literal -> no space before closing brace.
return false;
}
if (Right.getType() == TT_TrailingAnnotation &&
Right.isOneOf(tok::amp, tok::ampamp) &&
if (Right.is(TT_TrailingAnnotation) && Right.isOneOf(tok::amp, tok::ampamp) &&
Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
(!Right.Next || Right.Next->is(tok::semi))) {
// Match const and volatile ref-qualifiers without any additional
Expand Down
55 changes: 25 additions & 30 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,11 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
nextToken();
continue;
}
tok::TokenKind kind = FormatTok->Tok.getKind();
if (FormatTok->getType() == TT_MacroBlockBegin)
kind = tok::l_brace;
else if (FormatTok->getType() == TT_MacroBlockEnd)
kind = tok::r_brace;
tok::TokenKind Kind = FormatTok->Tok.getKind();
if (FormatTok->is(TT_MacroBlockBegin))
Kind = tok::l_brace;
else if (FormatTok->is(TT_MacroBlockEnd))
Kind = tok::r_brace;

auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
&HasLabel, &StatementCount] {
Expand All @@ -380,7 +380,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
assert(StatementCount > 0 && "StatementCount overflow!");
};

switch (kind) {
switch (Kind) {
case tok::comment:
nextToken();
addUnwrappedLine();
Expand Down Expand Up @@ -427,11 +427,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
break;
case tok::kw_default: {
unsigned StoredPosition = Tokens->getPosition();
FormatToken *Next;
do {
Next = Tokens->getNextToken();
assert(Next);
} while (Next->is(tok::comment));
auto *Next = Tokens->getNextNonComment();
FormatTok = Tokens->setPosition(StoredPosition);
if (Next->isNot(tok::colon)) {
// default not followed by ':' is not a case label; treat it like
Expand Down Expand Up @@ -495,20 +491,19 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
};
SmallVector<StackEntry, 8> LBraceStack;
assert(Tok->is(tok::l_brace));

do {
// Get next non-comment, non-preprocessor token.
FormatToken *NextTok;
do {
NextTok = Tokens->getNextToken();
} while (NextTok->is(tok::comment));
if (!Style.isTableGen()) {
// InTableGen, '#' is like binary operator. Not a preprocessor directive.
while (NextTok->is(tok::hash) && !Line->InMacroBody) {
NextTok = Tokens->getNextToken();
auto *NextTok = Tokens->getNextNonComment();

if (!Line->InMacroBody && !Style.isTableGen()) {
// Skip PPDirective lines and comments.
while (NextTok->is(tok::hash)) {
do {
NextTok = Tokens->getNextToken();
} while (NextTok->is(tok::comment) ||
(NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof)));
} while (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof));

while (NextTok->is(tok::comment))
NextTok = Tokens->getNextToken();
}
}

Expand Down Expand Up @@ -640,6 +635,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
default:
break;
}

PrevTok = Tok;
Tok = NextTok;
} while (Tok->isNot(tok::eof) && !LBraceStack.empty());
Expand Down Expand Up @@ -3277,8 +3273,8 @@ void UnwrappedLineParser::parseSwitch() {
}

// Operators that can follow a C variable.
static bool isCOperatorFollowingVar(tok::TokenKind kind) {
switch (kind) {
static bool isCOperatorFollowingVar(tok::TokenKind Kind) {
switch (Kind) {
case tok::ampamp:
case tok::ampequal:
case tok::arrow:
Expand Down Expand Up @@ -4706,14 +4702,13 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
do {
FormatTok = Tokens->getNextToken();
assert(FormatTok);
while (FormatTok->getType() == TT_ConflictStart ||
FormatTok->getType() == TT_ConflictEnd ||
FormatTok->getType() == TT_ConflictAlternative) {
if (FormatTok->getType() == TT_ConflictStart)
while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
TT_ConflictAlternative)) {
if (FormatTok->is(TT_ConflictStart))
conditionalCompilationStart(/*Unreachable=*/false);
else if (FormatTok->getType() == TT_ConflictAlternative)
else if (FormatTok->is(TT_ConflictAlternative))
conditionalCompilationAlternative();
else if (FormatTok->getType() == TT_ConflictEnd)
else if (FormatTok->is(TT_ConflictEnd))
conditionalCompilationEnd();
FormatTok = Tokens->getNextToken();
FormatTok->MustBreakBefore = true;
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
Style.ReferenceAlignment != FormatStyle::RAS_Right &&
Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
for (int Previous = i - 1;
Previous >= 0 &&
Changes[Previous].Tok->getType() == TT_PointerOrReference;
Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);
--Previous) {
assert(Changes[Previous].Tok->isPointerOrReference());
if (Changes[Previous].Tok->isNot(tok::star)) {
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,10 @@ static T extractMaskValue(T KeyPath) {

#define PARSE_OPTION_WITH_MARSHALLING( \
ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \
FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, \
ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, \
NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY)&options::CC1Option) { \
FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \
IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY) & options::CC1Option) { \
KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \
if (IMPLIED_CHECK) \
KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \
Expand All @@ -550,10 +550,10 @@ static T extractMaskValue(T KeyPath) {
// with lifetime extension of the reference.
#define GENERATE_OPTION_WITH_MARSHALLING( \
CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, \
KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY)&options::CC1Option) { \
VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \
IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY) & options::CC1Option) { \
[&](const auto &Extracted) { \
if (ALWAYS_EMIT || \
(Extracted != \
Expand Down
9 changes: 3 additions & 6 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,7 @@ void InitOnlyAction::ExecuteAction() {

// Basically PreprocessOnlyAction::ExecuteAction.
void ReadPCHAndPreprocessAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
AdjustCI(CI);

Preprocessor &PP = CI.getPreprocessor();
Preprocessor &PP = getCompilerInstance().getPreprocessor();

// Ignore unknown pragmas.
PP.IgnorePragmas();
Expand Down Expand Up @@ -453,6 +450,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
return "BuildingBuiltinDumpStructCall";
case CodeSynthesisContext::BuildingDeductionGuides:
return "BuildingDeductionGuides";
case CodeSynthesisContext::TypeAliasTemplateInstantiation:
return "TypeAliasTemplateInstantiation";
}
return "";
}
Expand Down Expand Up @@ -1191,8 +1190,6 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {

void GetDependenciesByModuleNameAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
AdjustCI(CI);

Preprocessor &PP = CI.getPreprocessor();
SourceManager &SM = PP.getSourceManager();
FileID MainFileID = SM.getMainFileID();
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,10 +720,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
if (LangOpts.CPlusPlus20) {
Builder.defineMacro("__cpp_aggregate_paren_init", "201902L");

// P0848 is implemented, but we're still waiting for other concepts
// issues to be addressed before bumping __cpp_concepts up to 202002L.
// Refer to the discussion of this at https://reviews.llvm.org/D128619.
Builder.defineMacro("__cpp_concepts", "201907L");
Builder.defineMacro("__cpp_concepts", "202002");
Builder.defineMacro("__cpp_conditional_explicit", "201806L");
Builder.defineMacro("__cpp_consteval", "202211L");
Builder.defineMacro("__cpp_constexpr_dynamic_alloc", "201907L");
Expand Down
112 changes: 112 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,118 @@ double3 abs(double3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
double4 abs(double4);

//===----------------------------------------------------------------------===//
// all builtins
//===----------------------------------------------------------------------===//

/// \fn bool all(T x)
/// \brief Returns True if all components of the \a x parameter are non-zero;
/// otherwise, false. \param x The input value.

#ifdef __HLSL_ENABLE_16_BIT
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t4);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t4);
#endif

_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half2);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half3);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool4);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double4);

//===----------------------------------------------------------------------===//
// any builtins
//===----------------------------------------------------------------------===//
Expand Down
17 changes: 9 additions & 8 deletions clang/lib/Headers/intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <intrin0.h>

/* First include the standard intrinsics. */
#if defined(__i386__) || defined(__x86_64__)
#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
#include <x86intrin.h>
#endif

Expand Down Expand Up @@ -166,7 +166,7 @@ unsigned __int32 xbegin(void);
void _xend(void);

/* These additional intrinsics are turned on in x64/amd64/x86_64 mode. */
#ifdef __x86_64__
#if defined(__x86_64__) && !defined(__arm64ec__)
void __addgsbyte(unsigned long, unsigned char);
void __addgsdword(unsigned long, unsigned long);
void __addgsqword(unsigned long, unsigned __int64);
Expand Down Expand Up @@ -236,7 +236,8 @@ __int64 _mul128(__int64, __int64, __int64 *);
/*----------------------------------------------------------------------------*\
|* movs, stos
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)

#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst,
unsigned char const *__src,
size_t __n) {
Expand Down Expand Up @@ -305,7 +306,7 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosw(unsigned short *__dst,
: "memory");
}
#endif
#ifdef __x86_64__
#if defined(__x86_64__) && !defined(__arm64ec__)
static __inline__ void __DEFAULT_FN_ATTRS __movsq(
unsigned long long *__dst, unsigned long long const *__src, size_t __n) {
__asm__ __volatile__("rep movsq"
Expand All @@ -324,7 +325,7 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
/*----------------------------------------------------------------------------*\
|* Misc
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
__asm__ volatile("hlt");
}
Expand All @@ -339,7 +340,7 @@ static __inline__ void __DEFAULT_FN_ATTRS __nop(void) {
/*----------------------------------------------------------------------------*\
|* MS AArch64 specific
\*----------------------------------------------------------------------------*/
#if defined(__aarch64__)
#if defined(__aarch64__) || defined(__arm64ec__)
unsigned __int64 __getReg(int);
long _InterlockedAdd(long volatile *Addend, long Value);
__int64 _InterlockedAdd64(__int64 volatile *Addend, __int64 Value);
Expand Down Expand Up @@ -383,7 +384,7 @@ void __cdecl __prefetch(void *);
/*----------------------------------------------------------------------------*\
|* Privileged intrinsics
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readmsr(unsigned long __register) {
// Loads the contents of a 64-bit model specific register (MSR) specified in
Expand All @@ -397,7 +398,6 @@ __readmsr(unsigned long __register) {
__asm__ ("rdmsr" : "=d"(__edx), "=a"(__eax) : "c"(__register));
return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax;
}
#endif

static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS __readcr3(void) {
unsigned __LPTRINT_TYPE__ __cr3_val;
Expand All @@ -413,6 +413,7 @@ static __inline__ void __DEFAULT_FN_ATTRS
__writecr3(unsigned __INTPTR_TYPE__ __cr3_val) {
__asm__ ("mov {%0, %%cr3|cr3, %0}" : : "r"(__cr3_val) : "memory");
}
#endif

#ifdef __cplusplus
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Headers/intrin0.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#ifndef __INTRIN0_H
#define __INTRIN0_H

#ifdef __x86_64__
#if defined(__x86_64__) && !defined(__arm64ec__)
#include <adcintrin.h>
#endif

Expand All @@ -27,7 +27,7 @@ unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
void _ReadWriteBarrier(void);

#if defined(__aarch64__)
#if defined(__aarch64__) || defined(__arm64ec__)
unsigned int _CountLeadingZeros(unsigned long);
unsigned int _CountLeadingZeros64(unsigned _int64);
unsigned char _InterlockedCompareExchange128_acq(__int64 volatile *_Destination,
Expand All @@ -44,7 +44,7 @@ unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination,
__int64 *_ComparandResult);
#endif

#ifdef __x86_64__
#ifdef __x86_64__ && !defined(__arm64ec__)
unsigned __int64 _umul128(unsigned __int64, unsigned __int64,
unsigned __int64 *);
unsigned __int64 __shiftleft128(unsigned __int64 _LowPart,
Expand All @@ -55,7 +55,7 @@ unsigned __int64 __shiftright128(unsigned __int64 _LowPart,
unsigned char _Shift);
#endif

#if defined(__x86_64__) || defined(__i386__)
#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
void _mm_pause(void);
#endif

Expand Down Expand Up @@ -83,7 +83,7 @@ __int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask);
__int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask);
#endif

#if defined(__arm__) || defined(__aarch64__)
#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange Add
\*----------------------------------------------------------------------------*/
Expand Down
1 change: 1 addition & 0 deletions clang/lib/InstallAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
)

add_clang_library(clangInstallAPI
DiagnosticBuilderWrappers.cpp
DylibVerifier.cpp
FileList.cpp
Frontend.cpp
Expand Down
110 changes: 110 additions & 0 deletions clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//===- DiagnosticBuilderWrappers.cpp ----------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DiagnosticBuilderWrappers.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/Platform.h"

using clang::DiagnosticBuilder;

namespace llvm {
namespace MachO {
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const Architecture &Arch) {
DB.AddString(getArchitectureName(Arch));
return DB;
}

const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const ArchitectureSet &ArchSet) {
DB.AddString(std::string(ArchSet));
return DB;
}

const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const PlatformType &Platform) {
DB.AddString(getPlatformName(Platform));
return DB;
}

const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const PlatformVersionSet &Platforms) {
std::string PlatformAsString;
raw_string_ostream Stream(PlatformAsString);

Stream << "[ ";
llvm::interleaveComma(
Platforms, Stream,
[&Stream](const std::pair<PlatformType, VersionTuple> &PV) {
Stream << getPlatformName(PV.first);
if (!PV.second.empty())
Stream << PV.second.getAsString();
});
Stream << " ]";
DB.AddString(Stream.str());
return DB;
}

const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const FileType &Type) {
switch (Type) {
case FileType::MachO_Bundle:
DB.AddString("mach-o bundle");
return DB;
case FileType::MachO_DynamicLibrary:
DB.AddString("mach-o dynamic library");
return DB;
case FileType::MachO_DynamicLibrary_Stub:
DB.AddString("mach-o dynamic library stub");
return DB;
case FileType::TBD_V1:
DB.AddString("tbd-v1");
return DB;
case FileType::TBD_V2:
DB.AddString("tbd-v2");
return DB;
case FileType::TBD_V3:
DB.AddString("tbd-v3");
return DB;
case FileType::TBD_V4:
DB.AddString("tbd-v4");
return DB;
case FileType::TBD_V5:
DB.AddString("tbd-v5");
return DB;
case FileType::Invalid:
case FileType::All:
break;
}
llvm_unreachable("Unexpected file type for diagnostics.");
}

const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const PackedVersion &Version) {
std::string VersionString;
raw_string_ostream OS(VersionString);
OS << Version;
DB.AddString(OS.str());
return DB;
}

const clang::DiagnosticBuilder &
operator<<(const clang::DiagnosticBuilder &DB,
const StringMapEntry<ArchitectureSet> &LibAttr) {
std::string IFAsString;
raw_string_ostream OS(IFAsString);

OS << LibAttr.getKey() << " [ " << LibAttr.getValue() << " ]";
DB.AddString(OS.str());
return DB;
}

} // namespace MachO
} // namespace llvm
49 changes: 49 additions & 0 deletions clang/lib/InstallAPI/DiagnosticBuilderWrappers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===- DiagnosticBuilderWrappers.h -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// Diagnostic wrappers for TextAPI types for error reporting.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H
#define LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H

#include "clang/Basic/Diagnostic.h"
#include "llvm/TextAPI/Architecture.h"
#include "llvm/TextAPI/ArchitectureSet.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/Platform.h"

namespace llvm {
namespace MachO {

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const PlatformType &Platform);

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const PlatformVersionSet &Platforms);

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const Architecture &Arch);

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const ArchitectureSet &ArchSet);

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const FileType &Type);

const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
const PackedVersion &Version);

const clang::DiagnosticBuilder &
operator<<(const clang::DiagnosticBuilder &DB,
const StringMapEntry<ArchitectureSet> &LibAttr);

} // namespace MachO
} // namespace llvm
#endif // LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H
Loading