753 changes: 753 additions & 0 deletions bolt/test/X86/Inputs/dwarf5-df-input-lowpc-ranges-other.s

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions bolt/test/X86/dwarf5-df-input-lowpc-ranges-cus.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
; RUN: rm -rf %t
; RUN: mkdir %t
; RUN: cd %t
; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-input-lowpc-ranges-main.s \
; RUN: -split-dwarf-file=main.dwo -o main.o
; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-input-lowpc-ranges-other.s \
; RUN: -split-dwarf-file=mainOther.dwo -o other.o
; RUN: %clang %cflags main.o other.o -o main.exe
; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
; RUN: llvm-dwarfdump --show-form --verbose --debug-rnglists main.exe.bolt &> %t/foo.txt
; RUN: llvm-dwarfdump --show-form --verbose --debug-addr main.exe.bolt >> %t/foo.txt
; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.bolt >> %t/foo.txt
; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s
; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo mainOther.dwo.dwo &> %t/mainddwodwo.txt
; RUN: cat %t/mainddwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s

;; Tests that BOLT correctly handles Skeleton CU which has DW_AT_low_pc/DW_AT_ranges as input and handles multiple CUs with ranges.

; BOLT: Addrs: [
; BOLT-NEXT: 0x[[#%.16x,ADDR1:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR2:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR3:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR4:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR5:]]

; BOLT: Addrs: [
; BOLT-NEXT: 0x[[#%.16x,ADDR6:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR7:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR8:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR9:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR10:]]

; BOLT: DW_TAG_skeleton_unit
; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "main.dwo.dwo")
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010
; BOLT-NEXT: [0x[[#ADDR1]], 0x[[#ADDR1 + 0x16]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x16]], 0x[[#ADDR1 + 0x24]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x24]], 0x[[#ADDR1 + 0x29]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x30]], 0x[[#ADDR1 + 0x46]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x50]], 0x[[#ADDR1 + 0x77]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x77]], 0x[[#ADDR1 + 0x85]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x85]], 0x[[#ADDR1 + 0x9f]])
; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008)
; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x0000000c)

; BOLT: DW_TAG_skeleton_unit
; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "mainOther.dwo.dwo")
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x0000003b
; BOLT-NEXT: [0x[[#ADDR6]], 0x[[#ADDR6 + 0x16]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x16]], 0x[[#ADDR6 + 0x24]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x24]], 0x[[#ADDR6 + 0x29]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x30]], 0x[[#ADDR6 + 0x46]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x50]], 0x[[#ADDR6 + 0x70]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x70]], 0x[[#ADDR6 + 0x7e]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x7e]], 0x[[#ADDR6 + 0x98]])
; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000038)
; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x00000037)

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014
; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000016)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000016, 0x0000000000000024)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000024, 0x0000000000000029))
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000020
; BOLT-DWO-MAIN-NEXT: [0x0000000000000002, 0x0000000000000029)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000029, 0x0000000000000037)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000037, 0x0000000000000051))

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014
; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000016)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000016, 0x0000000000000024)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000024, 0x0000000000000029))
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000020
; BOLT-DWO-MAIN-NEXT: [0x0000000000000002, 0x0000000000000022)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000022, 0x0000000000000030)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000030, 0x000000000000004a))
63 changes: 63 additions & 0 deletions bolt/test/X86/jt-symbol-disambiguation-4.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## If the operand references a symbol that differs from the jump table label,
## no reference updating is required even if its target address resides within
## the jump table's range.
## In this test case, consider the second instruction within the main function,
## where the address resulting from 'c + 17' corresponds to one byte beyond the
## address of the .LJTI2_0 jump table label. However, this operand represents
## an offset calculation related to the global variable 'c' and should remain
## unaffected by the jump table.

# REQUIRES: system-linux

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: %clang -no-pie %t.o -o %t.exe -Wl,-q
# RUN: llvm-bolt --funcs=main,foo/1 %t.exe -o %t.exe.bolt --print-normalized \
# RUN: 2>&1 | FileCheck %s

.text
.globl main
.type main,@function
main:
# CHECK: Binary Function "main"
pushq %rbp
movq %rsp, %rbp
movq $-16, %rax
movl c+17(%rax), %edx
# CHECK: movl c+17(%rax), %edx
cmpl $255, %edx
je .LCorrect
movl $1, %eax
popq %rbp
ret
.LCorrect:
movl $0, %eax
popq %rbp
ret

.p2align 4, 0x90
.type foo,@function
foo:
# CHECK: Binary Function "foo
movq $0, %rax
jmpq *.LJTI2_0(,%rax,8)
# CHECK: jmpq *{{.*}} # JUMPTABLE
addl $-36, %eax
.LBB2_2:
addl $-16, %eax
retq
.section .rodata,"a",@progbits
.type c,@object
.data
.globl c
.p2align 4, 0x0
c:
.byte 1
.byte 0xff
.zero 14
.size c, 16
.LJTI2_0:
.quad .LBB2_2
.quad .LBB2_2
.quad .LBB2_2
.quad .LBB2_2

18 changes: 18 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,16 @@ C++23 Feature Support
- Implemented `P1774R8: Portable assumptions <https://wg21.link/P1774R8>`_.

- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
Note, the ``-Winvalid-constexpr`` diagnostic is now disabled in C++23 mode,
but can be explicitly specified to retain the old diagnostic checking
behavior.

- Added a ``__reference_converts_from_temporary`` builtin, completing the necessary compiler support for
`P2255R2: Type trait to determine if a reference binds to a temporary <https://wg21.link/P2255R2>`_.

- Implemented `P2797R0: Static and explicit object member functions with the same parameter-type-lists <https://wg21.link/P2797R0>`_.
This completes the support for "deducing this".

C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -323,6 +329,17 @@ Non-comprehensive list of changes in this release
- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
now be used within constant expressions.

- When compiling a constexpr function, Clang will check to see whether the
function can *never* be used in a constant expression context and issues a
diagnostic under the ``-Winvalid-constexpr`` diagostic flag (which defaults
to an error). This check can be expensive because the mere presence of a
function marked ``constexpr`` will cause us to undergo constant expression
evaluation, even if the function is not called within the translation unit
being compiled. Due to the expense, Clang no longer checks constexpr function
bodies when the function is defined in a system header file or when
``-Winvalid-constexpr`` is not enabled for the function definition, which
should result in mild compile-time performance improvements.

New Compiler Flags
------------------
- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
Expand Down Expand Up @@ -982,6 +999,7 @@ AST Matchers
- Fixed ``forEachArgumentWithParam`` and ``forEachArgumentWithParamType`` to
not skip the explicit object parameter for operator calls.
- Fixed captureVars assertion failure if not capturesVariables. (#GH76425)
- ``forCallable`` now properly preserves binding on successful match. (#GH89657)

clang-format
------------
Expand Down
49 changes: 48 additions & 1 deletion clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ Warns when a nullable pointer is returned from a function that has _Nonnull retu
optin
^^^^^
Checkers for portability, performance or coding style specific rules.
Checkers for portability, performance, optional security and coding style specific rules.
.. _optin-core-EnumCastOutOfRange:
Expand Down Expand Up @@ -938,6 +938,53 @@ optin.portability.UnixAPI
"""""""""""""""""""""""""
Finds implementation-defined behavior in UNIX/Posix functions.
.. _optin-taint-TaintedAlloc:
optin.taint.TaintedAlloc (C, C++)
"""""""""""""""""""""""""""""""""
This checker warns for cases when the ``size`` parameter of the ``malloc`` ,
``calloc``, ``realloc``, ``alloca`` or the size parameter of the
array new C++ operator is tainted (potentially attacker controlled).
If an attacker can inject a large value as the size parameter, memory exhaustion
denial of service attack can be carried out.
The ``alpha.security.taint.TaintPropagation`` checker also needs to be enabled for
this checker to give warnings.
The analyzer emits warning only if it cannot prove that the size parameter is
within reasonable bounds (``<= SIZE_MAX/4``). This functionality partially
covers the SEI Cert coding standard rule `INT04-C
<https://wiki.sei.cmu.edu/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources>`_.
You can silence this warning either by bound checking the ``size`` parameter, or
by explicitly marking the ``size`` parameter as sanitized. See the
:ref:`alpha-security-taint-TaintPropagation` checker for more details.
.. code-block:: c
void vulnerable(void) {
size_t size = 0;
scanf("%zu", &size);
int *p = malloc(size); // warn: malloc is called with a tainted (potentially attacker controlled) value
free(p);
}
void not_vulnerable(void) {
size_t size = 0;
scanf("%zu", &size);
if (1024 < size)
return;
int *p = malloc(size); // No warning expected as the the user input is bound
free(p);
}
void vulnerable_cpp(void) {
size_t size = 0;
scanf("%zu", &size);
int *ptr = new int[size];// warn: Memory allocation function is called with a tainted (potentially attacker controlled) value
delete[] ptr;
}
.. _security-checkers:
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -2150,7 +2150,11 @@ enum CXCursorKind {
*/
CXCursor_OpenACCComputeConstruct = 320,

CXCursor_LastStmt = CXCursor_OpenACCComputeConstruct,
/** OpenACC Loop Construct.
*/
CXCursor_OpenACCLoopConstruct = 321,

CXCursor_LastStmt = CXCursor_OpenACCLoopConstruct,

/**
* Cursor that represents the translation unit itself.
Expand Down
11 changes: 6 additions & 5 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -3025,9 +3025,10 @@ class OverloadExpr : public Expr {

public:
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
bool HasFormOfMemberPointer;
OverloadExpr *Expression = nullptr;
bool IsAddressOfOperand = false;
bool IsAddressOfOperandWithParen = false;
bool HasFormOfMemberPointer = false;
};

/// Finds the overloaded expression in the given expression \p E of
Expand All @@ -3039,6 +3040,7 @@ class OverloadExpr : public Expr {
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));

FindResult Result;
bool HasParen = isa<ParenExpr>(E);

E = E->IgnoreParens();
if (isa<UnaryOperator>(E)) {
Expand All @@ -3048,10 +3050,9 @@ class OverloadExpr : public Expr {

Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
Result.IsAddressOfOperand = true;
Result.IsAddressOfOperandWithParen = HasParen;
Result.Expression = Ovl;
} else {
Result.HasFormOfMemberPointer = false;
Result.IsAddressOfOperand = false;
Result.Expression = cast<OverloadExpr>(E);
}

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4000,6 +4000,8 @@ bool RecursiveASTVisitor<Derived>::VisitOpenACCClauseList(

DEF_TRAVERSE_STMT(OpenACCComputeConstruct,
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
DEF_TRAVERSE_STMT(OpenACCLoopConstruct,
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })

// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
Expand Down
71 changes: 70 additions & 1 deletion clang/include/clang/AST/StmtOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
}
};

class OpenACCLoopConstruct;
/// This class represents a compute construct, representing a 'Kind' of
/// `parallel', 'serial', or 'kernel'. These constructs are associated with a
/// 'structured block', defined as:
Expand Down Expand Up @@ -165,6 +167,11 @@ class OpenACCComputeConstruct final
}

void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
// Serialization helper function that searches the structured block for 'loop'
// constructs that should be associated with this, and sets their parent
// compute construct to this one. This isn't necessary normally, since we have
// the ability to record the state during parsing.
void findAndSetChildLoops();

public:
static bool classof(const Stmt *T) {
Expand All @@ -176,12 +183,74 @@ class OpenACCComputeConstruct final
static OpenACCComputeConstruct *
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
SourceLocation DirectiveLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock);
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock,
ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs);

Stmt *getStructuredBlock() { return getAssociatedStmt(); }
const Stmt *getStructuredBlock() const {
return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
}
};
/// This class represents a 'loop' construct. The 'loop' construct applies to a
/// 'for' loop (or range-for loop), and is optionally associated with a Compute
/// Construct.
class OpenACCLoopConstruct final
: public OpenACCAssociatedStmtConstruct,
public llvm::TrailingObjects<OpenACCLoopConstruct,
const OpenACCClause *> {
// The compute construct this loop is associated with, or nullptr if this is
// an orphaned loop construct, or if it hasn't been set yet. Because we
// construct the directives at the end of their statement, the 'parent'
// construct is not yet available at the time of construction, so this needs
// to be set 'later'.
const OpenACCComputeConstruct *ParentComputeConstruct = nullptr;

friend class ASTStmtWriter;
friend class ASTStmtReader;
friend class ASTContext;
friend class OpenACCComputeConstruct;

OpenACCLoopConstruct(unsigned NumClauses);

OpenACCLoopConstruct(SourceLocation Start, SourceLocation DirLoc,
SourceLocation End,
ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
void setLoop(Stmt *Loop);

void setParentComputeConstruct(OpenACCComputeConstruct *CC) {
assert(!ParentComputeConstruct && "Parent already set?");
ParentComputeConstruct = CC;
}

public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpenACCLoopConstructClass;
}

static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C,
unsigned NumClauses);

static OpenACCLoopConstruct *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation DirLoc,
SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses,
Stmt *Loop);

Stmt *getLoop() { return getAssociatedStmt(); }
const Stmt *getLoop() const {
return const_cast<OpenACCLoopConstruct *>(this)->getLoop();
}

/// OpenACC 3.3 2.9:
/// An orphaned loop construct is a loop construct that is not lexically
/// enclosed within a compute construct. The parent compute construct of a
/// loop construct is the nearest compute construct that lexically contains
/// the loop construct.
bool isOrphanedLoopConstruct() const {
return ParentComputeConstruct == nullptr;
}
const OpenACCComputeConstruct *getParentComputeConstruct() const {
return ParentComputeConstruct;
}
};
} // namespace clang
#endif // LLVM_CLANG_AST_STMTOPENACC_H
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ class TextNodeDumper
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S);
};

} // namespace clang
Expand Down
16 changes: 12 additions & 4 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -8371,20 +8371,28 @@ AST_MATCHER_P(Stmt, forCallable, internal::Matcher<Decl>, InnerMatcher) {
const auto &CurNode = Stack.back();
Stack.pop_back();
if (const auto *FuncDeclNode = CurNode.get<FunctionDecl>()) {
if (InnerMatcher.matches(*FuncDeclNode, Finder, Builder)) {
BoundNodesTreeBuilder B = *Builder;
if (InnerMatcher.matches(*FuncDeclNode, Finder, &B)) {
*Builder = std::move(B);
return true;
}
} else if (const auto *LambdaExprNode = CurNode.get<LambdaExpr>()) {
BoundNodesTreeBuilder B = *Builder;
if (InnerMatcher.matches(*LambdaExprNode->getCallOperator(), Finder,
Builder)) {
&B)) {
*Builder = std::move(B);
return true;
}
} else if (const auto *ObjCMethodDeclNode = CurNode.get<ObjCMethodDecl>()) {
if (InnerMatcher.matches(*ObjCMethodDeclNode, Finder, Builder)) {
BoundNodesTreeBuilder B = *Builder;
if (InnerMatcher.matches(*ObjCMethodDeclNode, Finder, &B)) {
*Builder = std::move(B);
return true;
}
} else if (const auto *BlockDeclNode = CurNode.get<BlockDecl>()) {
if (InnerMatcher.matches(*BlockDeclNode, Finder, Builder)) {
BoundNodesTreeBuilder B = *Builder;
if (InnerMatcher.matches(*BlockDeclNode, Finder, &B)) {
*Builder = std::move(B);
return true;
}
} else {
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/Cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ enum class CudaArch {
GFX803,
GFX805,
GFX810,
GFX9_GENERIC,
GFX900,
GFX902,
GFX904,
Expand All @@ -102,23 +103,27 @@ enum class CudaArch {
GFX940,
GFX941,
GFX942,
GFX10_1_GENERIC,
GFX1010,
GFX1011,
GFX1012,
GFX1013,
GFX10_3_GENERIC,
GFX1030,
GFX1031,
GFX1032,
GFX1033,
GFX1034,
GFX1035,
GFX1036,
GFX11_GENERIC,
GFX1100,
GFX1101,
GFX1102,
GFX1103,
GFX1150,
GFX1151,
GFX12_GENERIC,
GFX1200,
GFX1201,
Generic, // A processor model named 'generic' if the target backend defines a
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -12398,7 +12398,7 @@ def err_acc_var_not_pointer_type
def note_acc_expected_pointer_var : Note<"expected variable of pointer type">;
def err_acc_clause_after_device_type
: Error<"OpenACC clause '%0' may not follow a '%1' clause in a "
"compute construct">;
"%select{'%3'|compute}2 construct">;
def err_acc_reduction_num_gangs_conflict
: Error<
"OpenACC 'reduction' clause may not appear on a 'parallel' construct "
Expand All @@ -12413,6 +12413,9 @@ def err_acc_reduction_composite_type
def err_acc_reduction_composite_member_type :Error<
"OpenACC 'reduction' composite variable must not have non-scalar field">;
def note_acc_reduction_composite_member_loc : Note<"invalid field is here">;
def err_acc_loop_not_for_loop
: Error<"OpenACC 'loop' construct can only be applied to a 'for' loop">;
def note_acc_construct_here : Note<"'%0' construct is here">;

// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,14 @@ COMPATIBLE_LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process sta

BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NULL")

// FIXME: It would be better for us to find a way to encode the state of this
// diagnostic in tablegen so that we can specify a particular diagnostic option
// is disabled or enabled based on other language options or made it easier to
// do this from the compiler invocation without hitting option round-tripping
// issues.
BENIGN_LANGOPT(CheckConstexprFunctionBodies, 1, 1,
"Emit diagnostics for a constexpr function body that can never "
"be used in a constant expression.")
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,4 @@ def OpenACCConstructStmt : StmtNode<Stmt, /*abstract=*/1>;
def OpenACCAssociatedStmtConstruct
: StmtNode<OpenACCConstructStmt, /*abstract=*/1>;
def OpenACCComputeConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
def OpenACCLoopConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
20 changes: 19 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,17 @@ multiclass BoolMOption<string flag_base, KeyPathAndMacro kpm,
Group<m_Group>;
}

/// Creates a BoolOption where both of the flags are prefixed with "W", are in
/// the Group<W_Group>.
/// Used for -cc1 frontend options. Driver-only options do not map to
/// CompilerInvocation.
multiclass BoolWOption<string flag_base, KeyPathAndMacro kpm,
Default default, FlagDef flag1, FlagDef flag2,
BothFlags both = BothFlags<[]>> {
defm NAME : BoolOption<"W", flag_base, kpm, default, flag1, flag2, both>,
Group<W_Group>;
}

// Works like BoolOption except without marshalling
multiclass BoolOptionWithoutMarshalling<string prefix = "", string spelling_base,
FlagDef flag1_base, FlagDef flag2_base,
Expand Down Expand Up @@ -606,6 +617,7 @@ defvar cpp11 = LangOpts<"CPlusPlus11">;
defvar cpp14 = LangOpts<"CPlusPlus14">;
defvar cpp17 = LangOpts<"CPlusPlus17">;
defvar cpp20 = LangOpts<"CPlusPlus20">;
defvar cpp23 = LangOpts<"CPlusPlus23">;
defvar c99 = LangOpts<"C99">;
defvar c23 = LangOpts<"C23">;
defvar lang_std = LangOpts<"LangStd">;
Expand Down Expand Up @@ -961,6 +973,12 @@ def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>,
HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>,
Visibility<[ClangOption, CC1Option]>;
defm invalid_constexpr : BoolWOption<"invalid-constexpr",
LangOpts<"CheckConstexprFunctionBodies">,
Default<!strconcat("!", cpp23.KeyPath)>,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Disable">,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
BothFlags<[], [ClangOption, CC1Option], " checking of constexpr function bodies for validity within a constant expression context">>;
def Wl_COMMA : CommaJoined<["-"], "Wl,">, Visibility<[ClangOption, FlangOption]>,
Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass the comma separated arguments in <arg> to the linker">,
Expand Down Expand Up @@ -3574,7 +3592,7 @@ def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group<
HelpText<"Do not create a host fallback if offloading to the device fails.">,
MarshallingInfoFlag<LangOpts<"OpenMPOffloadMandatory">>;
def fopenmp_force_usm : Flag<["-"], "fopenmp-force-usm">, Group<f_Group>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Force behvaior as if the user specified pragma omp requires unified_shared_memory.">,
MarshallingInfoFlag<LangOpts<"OpenMPForceUSM">>;
def fopenmp_target_jit : Flag<["-"], "fopenmp-target-jit">, Group<f_Group>,
Expand Down
156 changes: 156 additions & 0 deletions clang/include/clang/Sema/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@
#ifndef LLVM_CLANG_SEMA_ATTR_H
#define LLVM_CLANG_SEMA_ATTR_H

#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/SemaBase.h"
#include "llvm/Support/Casting.h"

namespace clang {
Expand All @@ -32,5 +41,152 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
}

/// Return true if the given decl has a declarator that should have
/// been processed by Sema::GetTypeForDeclarator.
inline bool hasDeclarator(const Decl *D) {
// In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
}

/// hasFunctionProto - Return true if the given decl has a argument
/// information. This decl should have already passed
/// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
inline bool hasFunctionProto(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return isa<FunctionProtoType>(FnTy);
return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
}

/// getFunctionOrMethodNumParams - Return number of function or method
/// parameters. It is an error to call this on a K&R function (use
/// hasFunctionProto first).
inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getNumParams();
if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getNumParams();
return cast<ObjCMethodDecl>(D)->param_size();
}

inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
unsigned Idx) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getParamDecl(Idx);
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getParamDecl(Idx);
if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getParamDecl(Idx);
return nullptr;
}

inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->getParamDecl(Idx)->getType();

return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
}

inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
if (auto *PVD = getFunctionOrMethodParam(D, Idx))
return PVD->getSourceRange();
return SourceRange();
}

inline QualType getFunctionOrMethodResultType(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return FnTy->getReturnType();
return cast<ObjCMethodDecl>(D)->getReturnType();
}

inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getReturnTypeSourceRange();
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getReturnTypeSourceRange();
return SourceRange();
}

inline bool isFunctionOrMethodVariadic(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->isVariadic();
if (const auto *BD = dyn_cast<BlockDecl>(D))
return BD->isVariadic();
return cast<ObjCMethodDecl>(D)->isVariadic();
}

inline bool isInstanceMethod(const Decl *D) {
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
return MethodDecl->isInstance();
return false;
}

/// Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const ParsedAttr &AL) {
if (const auto *A = D->getAttr<AttrTy>()) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< AL << A
<< (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
return false;
}

template <typename AttrTy>
bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const Attr &AL) {
if (const auto *A = D->getAttr<AttrTy>()) {
S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
<< &AL << A
<< (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
return false;
}

template <typename... DiagnosticArgs>
const SemaBase::SemaDiagnosticBuilder &
appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr) {
return Bldr;
}

template <typename T, typename... DiagnosticArgs>
const SemaBase::SemaDiagnosticBuilder &
appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
DiagnosticArgs &&...ExtraArgs) {
return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
std::forward<DiagnosticArgs>(ExtraArgs)...);
}

/// Applies the given attribute to the Decl without performing any
/// additional semantic checking.
template <typename AttrType>
void handleSimpleAttribute(SemaBase &S, Decl *D,
const AttributeCommonInfo &CI) {
D->addAttr(::new (S.getASTContext()) AttrType(S.getASTContext(), CI));
}

/// Add an attribute @c AttrType to declaration @c D, provided that
/// @c PassesCheck is true.
/// Otherwise, emit diagnostic @c DiagID, passing in all parameters
/// specified in @c ExtraArgs.
template <typename AttrType, typename... DiagnosticArgs>
void handleSimpleAttributeOrDiagnose(SemaBase &S, Decl *D,
const AttributeCommonInfo &CI,
bool PassesCheck, unsigned DiagID,
DiagnosticArgs &&...ExtraArgs) {
if (!PassesCheck) {
SemaBase::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
return;
}
handleSimpleAttribute<AttrType>(S, D, CI);
}

} // namespace clang
#endif // LLVM_CLANG_SEMA_ATTR_H
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ class Sema;
/// object argument.
bool IgnoreObjectArgument : 1;

bool TookAddressOfOverload : 1;

/// True if the candidate was found using ADL.
CallExpr::ADLCallKind IsADLCandidate : 1;

Expand Down Expand Up @@ -999,6 +1001,10 @@ class Sema;
/// Initialization of an object of class type by constructor,
/// using either a parenthesized or braced list of arguments.
CSK_InitByConstructor,

/// C++ [over.match.call.general]
/// Resolve a call through the address of an overload set.
CSK_AddressOfOverloadSet,
};

/// Information about operator rewrites to consider when adding operator
Expand Down
100 changes: 82 additions & 18 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/CleanupInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
Expand Down Expand Up @@ -171,21 +172,26 @@ class PseudoObjectExpr;
class QualType;
class SemaAMDGPU;
class SemaARM;
class SemaAVR;
class SemaBPF;
class SemaCodeCompletion;
class SemaCUDA;
class SemaHLSL;
class SemaHexagon;
class SemaLoongArch;
class SemaM68k;
class SemaMIPS;
class SemaMSP430;
class SemaNVPTX;
class SemaObjC;
class SemaOpenACC;
class SemaOpenCL;
class SemaOpenMP;
class SemaPPC;
class SemaPseudoObject;
class SemaRISCV;
class SemaSYCL;
class SemaSwift;
class SemaSystemZ;
class SemaWasm;
class SemaX86;
Expand Down Expand Up @@ -1011,6 +1017,11 @@ class Sema final : public SemaBase {
return *ARMPtr;
}

SemaAVR &AVR() {
assert(AVRPtr);
return *AVRPtr;
}

SemaBPF &BPF() {
assert(BPFPtr);
return *BPFPtr;
Expand Down Expand Up @@ -1041,11 +1052,21 @@ class Sema final : public SemaBase {
return *LoongArchPtr;
}

SemaM68k &M68k() {
assert(M68kPtr);
return *M68kPtr;
}

SemaMIPS &MIPS() {
assert(MIPSPtr);
return *MIPSPtr;
}

SemaMSP430 &MSP430() {
assert(MSP430Ptr);
return *MSP430Ptr;
}

SemaNVPTX &NVPTX() {
assert(NVPTXPtr);
return *NVPTXPtr;
Expand All @@ -1061,6 +1082,11 @@ class Sema final : public SemaBase {
return *OpenACCPtr;
}

SemaOpenCL &OpenCL() {
assert(OpenCLPtr);
return *OpenCLPtr;
}

SemaOpenMP &OpenMP() {
assert(OpenMPPtr && "SemaOpenMP is dead");
return *OpenMPPtr;
Expand All @@ -1086,6 +1112,11 @@ class Sema final : public SemaBase {
return *SYCLPtr;
}

SemaSwift &Swift() {
assert(SwiftPtr);
return *SwiftPtr;
}

SemaSystemZ &SystemZ() {
assert(SystemZPtr);
return *SystemZPtr;
Expand Down Expand Up @@ -1133,21 +1164,26 @@ class Sema final : public SemaBase {

std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
std::unique_ptr<SemaARM> ARMPtr;
std::unique_ptr<SemaAVR> AVRPtr;
std::unique_ptr<SemaBPF> BPFPtr;
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
std::unique_ptr<SemaCUDA> CUDAPtr;
std::unique_ptr<SemaHLSL> HLSLPtr;
std::unique_ptr<SemaHexagon> HexagonPtr;
std::unique_ptr<SemaLoongArch> LoongArchPtr;
std::unique_ptr<SemaM68k> M68kPtr;
std::unique_ptr<SemaMIPS> MIPSPtr;
std::unique_ptr<SemaMSP430> MSP430Ptr;
std::unique_ptr<SemaNVPTX> NVPTXPtr;
std::unique_ptr<SemaObjC> ObjCPtr;
std::unique_ptr<SemaOpenACC> OpenACCPtr;
std::unique_ptr<SemaOpenCL> OpenCLPtr;
std::unique_ptr<SemaOpenMP> OpenMPPtr;
std::unique_ptr<SemaPPC> PPCPtr;
std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
std::unique_ptr<SemaRISCV> RISCVPtr;
std::unique_ptr<SemaSYCL> SYCLPtr;
std::unique_ptr<SemaSwift> SwiftPtr;
std::unique_ptr<SemaSystemZ> SystemZPtr;
std::unique_ptr<SemaWasm> WasmPtr;
std::unique_ptr<SemaX86> X86Ptr;
Expand Down Expand Up @@ -3711,8 +3747,6 @@ class Sema final : public SemaBase {
const AttributeCommonInfo &CI,
const IdentifierInfo *Ident);
MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
StringRef Name);
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
const AttributeCommonInfo &CI);
InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
Expand All @@ -3726,8 +3760,6 @@ class Sema final : public SemaBase {
const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr,
CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget);

void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
ParameterABI ABI);
bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);

/// Create an CUDALaunchBoundsAttr attribute.
Expand All @@ -3742,20 +3774,6 @@ class Sema final : public SemaBase {
Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);

enum class RetainOwnershipKind { NS, CF, OS };
void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
RetainOwnershipKind K, bool IsTemplateInstantiation);

bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);

/// Do a check to make sure \p Name looks like a legal argument for the
/// swift_name attribute applied to decl \p D. Raise a diagnostic if the name
/// is invalid for the given declaration.
///
/// \p AL is used to provide caret diagnostics in case of a malformed name.
///
/// \returns true if the name is a valid swift name for \p D, false otherwise.
bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
const ParsedAttr &AL, bool IsAsync);

UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
Expand Down Expand Up @@ -3825,6 +3843,52 @@ class Sema final : public SemaBase {

void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);

/// Check if IdxExpr is a valid parameter index for a function or
/// instance method D. May output an error.
///
/// \returns true if IdxExpr is a valid index.
template <typename AttrInfo>
bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
unsigned AttrArgNum,
const Expr *IdxExpr, ParamIdx &Idx,
bool CanIndexImplicitThis = false) {
assert(isFunctionOrMethodOrBlockForAttrSubject(D));

// In C++ the implicit 'this' function parameter also counts.
// Parameters are counted from one.
bool HP = hasFunctionProto(D);
bool HasImplicitThisParam = isInstanceMethod(D);
bool IV = HP && isFunctionOrMethodVariadic(D);
unsigned NumParams =
(HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;

std::optional<llvm::APSInt> IdxInt;
if (IdxExpr->isTypeDependent() ||
!(IdxInt = IdxExpr->getIntegerConstantExpr(Context))) {
Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
<< &AI << AttrArgNum << AANT_ArgumentIntegerConstant
<< IdxExpr->getSourceRange();
return false;
}

unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
<< &AI << AttrArgNum << IdxExpr->getSourceRange();
return false;
}
if (HasImplicitThisParam && !CanIndexImplicitThis) {
if (IdxSource == 1) {
Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
<< &AI << IdxExpr->getSourceRange();
return false;
}
}

Idx = ParamIdx(IdxSource, D);
return true;
}

///@}

//
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/Sema/SemaARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
#ifndef LLVM_CLANG_SEMA_SEMAARM_H
#define LLVM_CLANG_SEMA_SEMAARM_H

#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"
#include "llvm/ADT/SmallVector.h"
#include <tuple>

namespace clang {
class ParsedAttr;

class SemaARM : public SemaBase {
public:
Expand Down Expand Up @@ -54,6 +56,15 @@ class SemaARM : public SemaBase {
bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
unsigned ExpectedFieldNum, bool AllowName);
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);

bool MveAliasValid(unsigned BuiltinID, StringRef AliasName);
bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName);
bool SveAliasValid(unsigned BuiltinID, StringRef AliasName);
bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName);
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL);
void handleNewAttr(Decl *D, const ParsedAttr &AL);
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
};

SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
Expand Down
32 changes: 32 additions & 0 deletions clang/include/clang/Sema/SemaAVR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===----- SemaAVR.h ------- AVR target-specific routines -----*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to AVR.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAAVR_H
#define LLVM_CLANG_SEMA_SEMAAVR_H

#include "clang/Sema/SemaBase.h"

namespace clang {
class Decl;
class ParsedAttr;

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

void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
void handleSignalAttr(Decl *D, const ParsedAttr &AL);
};

} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAAVR_H
7 changes: 7 additions & 0 deletions clang/include/clang/Sema/SemaBPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@
#ifndef LLVM_CLANG_SEMA_SEMABPF_H
#define LLVM_CLANG_SEMA_SEMABPF_H

#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class ParsedAttr;

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

bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

void handlePreserveAIRecord(RecordDecl *RD);
void handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <initializer_list>

namespace clang {
class ParsedAttr;

class SemaHLSL : public SemaBase {
public:
Expand All @@ -50,6 +51,13 @@ class SemaHLSL : public SemaBase {
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);

void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
};

} // namespace clang
Expand Down
30 changes: 30 additions & 0 deletions clang/include/clang/Sema/SemaM68k.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----- SemaM68k.h ------ M68k target-specific routines ----*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to M68k.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAM68K_H
#define LLVM_CLANG_SEMA_SEMAM68K_H

#include "clang/Sema/SemaBase.h"

namespace clang {
class Decl;
class ParsedAttr;

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

void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAM68K_H
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/SemaMIPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
#ifndef LLVM_CLANG_SEMA_SEMAMIPS_H
#define LLVM_CLANG_SEMA_SEMAMIPS_H

#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class ParsedAttr;

class SemaMIPS : public SemaBase {
public:
SemaMIPS(Sema &S);
Expand All @@ -27,6 +30,7 @@ class SemaMIPS : public SemaBase {
bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

Expand Down
30 changes: 30 additions & 0 deletions clang/include/clang/Sema/SemaMSP430.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----- SemaMSP430.h --- MSP430 target-specific routines ---*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to MSP430.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAMSP430_H
#define LLVM_CLANG_SEMA_SEMAMSP430_H

#include "clang/Sema/SemaBase.h"

namespace clang {
class Decl;
class ParsedAttr;

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

void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAMSP430_H
52 changes: 51 additions & 1 deletion clang/include/clang/Sema/SemaObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Redeclaration.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
Expand All @@ -45,6 +44,7 @@
namespace clang {

enum class CheckedConversionKind;
class ParsedAttr;
struct SkipBodyInfo;

class SemaObjC : public SemaBase {
Expand Down Expand Up @@ -1007,6 +1007,56 @@ class SemaObjC : public SemaBase {
ObjCInterfaceDecl *IDecl);

///@}

//
//
// -------------------------------------------------------------------------
//
//

/// \name ObjC Attributes
/// Implementations are in SemaObjC.cpp
///@{

bool isNSStringType(QualType T, bool AllowNSAttributedString = false);
bool isCFStringType(QualType T);

void handleIBOutlet(Decl *D, const ParsedAttr &AL);
void handleIBOutletCollection(Decl *D, const ParsedAttr &AL);

void handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL);
void handleDirectAttr(Decl *D, const ParsedAttr &AL);
void handleDirectMembersAttr(Decl *D, const ParsedAttr &AL);
void handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL);
void handleNSObject(Decl *D, const ParsedAttr &AL);
void handleIndependentClass(Decl *D, const ParsedAttr &AL);
void handleBlocksAttr(Decl *D, const ParsedAttr &AL);
void handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs);
void handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL);
void handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs);
void handleNSErrorDomain(Decl *D, const ParsedAttr &Attr);
void handleBridgeAttr(Decl *D, const ParsedAttr &AL);
void handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL);
void handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL);
void handleDesignatedInitializer(Decl *D, const ParsedAttr &AL);
void handleRuntimeName(Decl *D, const ParsedAttr &AL);
void handleBoxable(Decl *D, const ParsedAttr &AL);
void handleOwnershipAttr(Decl *D, const ParsedAttr &AL);
void handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL);
void handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL);

void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
Sema::RetainOwnershipKind K,
bool IsTemplateInstantiation);

/// \return whether the parameter is a pointer to OSObject pointer.
bool isValidOSObjectOutParameter(const Decl *D);
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);

Sema::RetainOwnershipKind
parsedAttrToRetainOwnershipKind(const ParsedAttr &AL);

///@}
};

} // namespace clang
Expand Down
27 changes: 26 additions & 1 deletion clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_CLANG_SEMA_SEMAOPENACC_H

#include "clang/AST/DeclGroup.h"
#include "clang/AST/StmtOpenACC.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Ownership.h"
Expand All @@ -25,6 +26,15 @@ namespace clang {
class OpenACCClause;

class SemaOpenACC : public SemaBase {
private:
/// A collection of loop constructs in the compute construct scope that
/// haven't had their 'parent' compute construct set yet. Entires will only be
/// made to this list in the case where we know the loop isn't an orphan.
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
/// Whether we are inside of a compute construct, and should add loops to the
/// above collection.
bool InsideComputeConstruct = false;

public:
// Redeclaration of the version in OpenACCClause.h.
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
Expand Down Expand Up @@ -394,7 +404,8 @@ class SemaOpenACC : public SemaBase {
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc);
/// Called when we encounter an associated statement for our construct, this
/// should check legality of the statement as it appertains to this Construct.
StmtResult ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt);
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
OpenACCDirectiveKind K, StmtResult AssocStmt);

/// Called after the directive has been completely parsed, including the
/// declaration group or associated statement.
Expand Down Expand Up @@ -431,6 +442,20 @@ class SemaOpenACC : public SemaBase {
Expr *LowerBound,
SourceLocation ColonLocFirst, Expr *Length,
SourceLocation RBLoc);

/// Helper type for the registration/assignment of constructs that need to
/// 'know' about their parent constructs and hold a reference to them, such as
/// Loop needing its parent construct.
class AssociatedStmtRAII {
SemaOpenACC &SemaRef;
bool WasInsideComputeConstruct;
OpenACCDirectiveKind DirKind;
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;

public:
AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind);
~AssociatedStmtRAII();
};
};

} // namespace clang
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/Sema/SemaOpenCL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----- SemaOpenCL.h --- Semantic Analysis for OpenCL 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 routines for OpenCL.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAOPENCL_H
#define LLVM_CLANG_SEMA_SEMAOPENCL_H

#include "clang/Sema/SemaBase.h"

namespace clang {
class Decl;
class ParsedAttr;

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

void handleNoSVMAttr(Decl *D, const ParsedAttr &AL);
void handleAccessAttr(Decl *D, const ParsedAttr &AL);

// Handles intel_reqd_sub_group_size.
void handleSubGroupSize(Decl *D, const ParsedAttr &AL);
};

} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAOPENCL_H
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/SemaOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <utility>

namespace clang {
class ParsedAttr;

class SemaOpenMP : public SemaBase {
public:
Expand Down Expand Up @@ -1348,6 +1349,8 @@ class SemaOpenMP : public SemaBase {
SourceLocation LLoc, SourceLocation RLoc,
ArrayRef<OMPIteratorData> Data);

void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL);

private:
void *VarDataSharingAttributesStack;

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/SemaRISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <memory>

namespace clang {
class ParsedAttr;

class SemaRISCV : public SemaBase {
public:
SemaRISCV(Sema &S);
Expand All @@ -36,6 +38,9 @@ class SemaRISCV : public SemaBase {

bool isValidRVVBitcast(QualType srcType, QualType destType);

void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
bool isAliasValid(unsigned BuiltinID, StringRef AliasName);

/// Indicate RISC-V vector builtin functions enabled or not.
bool DeclareRVVBuiltins = false;

Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/SemaSYCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "llvm/ADT/DenseSet.h"

namespace clang {
class Decl;
class ParsedAttr;

class SemaSYCL : public SemaBase {
public:
Expand Down Expand Up @@ -58,6 +60,8 @@ class SemaSYCL : public SemaBase {
SourceLocation LParen,
SourceLocation RParen,
ParsedType ParsedTy);

void handleKernelAttr(Decl *D, const ParsedAttr &AL);
};

} // namespace clang
Expand Down
59 changes: 59 additions & 0 deletions clang/include/clang/Sema/SemaSwift.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===----- SemaSwift.h --- Swift language-specific routines ---*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to Swift.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMASWIFT_H
#define LLVM_CLANG_SEMA_SEMASWIFT_H

#include "clang/AST/Attr.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/SemaBase.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
class AttributeCommonInfo;
class Decl;
class ParsedAttr;
class SwiftNameAttr;

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

SwiftNameAttr *mergeNameAttr(Decl *D, const SwiftNameAttr &SNA,
StringRef Name);

void handleAttrAttr(Decl *D, const ParsedAttr &AL);
void handleAsyncAttr(Decl *D, const ParsedAttr &AL);
void handleBridge(Decl *D, const ParsedAttr &AL);
void handleError(Decl *D, const ParsedAttr &AL);
void handleAsyncError(Decl *D, const ParsedAttr &AL);
void handleName(Decl *D, const ParsedAttr &AL);
void handleAsyncName(Decl *D, const ParsedAttr &AL);
void handleNewType(Decl *D, const ParsedAttr &AL);

/// Do a check to make sure \p Name looks like a legal argument for the
/// swift_name attribute applied to decl \p D. Raise a diagnostic if the name
/// is invalid for the given declaration.
///
/// \p AL is used to provide caret diagnostics in case of a malformed name.
///
/// \returns true if the name is a valid swift name for \p D, false otherwise.
bool DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
const ParsedAttr &AL, bool IsAsync);
void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
ParameterABI abi);
};

} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMASWIFT_H
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/SemaX86.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@
#ifndef LLVM_CLANG_SEMA_SEMAX86_H
#define LLVM_CLANG_SEMA_SEMAX86_H

#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class ParsedAttr;

class SemaX86 : public SemaBase {
public:
SemaX86(Sema &S);
Expand All @@ -32,6 +35,9 @@ class SemaX86 : public SemaBase {
ArrayRef<int> ArgNums);
bool CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);

void handleAnyInterruptAttr(Decl *D, const ParsedAttr &AL);
void handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,7 @@ enum StmtCode {

// OpenACC Constructs
STMT_OPENACC_COMPUTE_CONSTRUCT,
STMT_OPENACC_LOOP_CONSTRUCT,
};

/// The kinds of designators that can occur in a
Expand Down
21 changes: 21 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ def CoreAlpha : Package<"core">, ParentPackage<Alpha>;
// Note: OptIn is *not* intended for checkers that are too noisy to be on by
// default. Such checkers belong in the alpha package.
def OptIn : Package<"optin">;

def CoreOptIn : Package<"core">, ParentPackage<OptIn>;

// In the Portability package reside checkers for finding code that relies on
// implementation-defined behavior. Such checks are wanted for cross-platform
// development, but unwanted for developers who target only a single platform.
def PortabilityOptIn : Package<"portability">, ParentPackage<OptIn>;

// Optional checkers related to taint security analysis.
def TaintOptIn : Package<"taint">, ParentPackage<OptIn>;

def Nullability : Package<"nullability">,
PackageOptions<[
CmdLineOption<Boolean,
Expand Down Expand Up @@ -1718,6 +1722,23 @@ def UnixAPIPortabilityChecker : Checker<"UnixAPI">,

} // end optin.portability


//===----------------------------------------------------------------------===//
// Taint checkers.
//===----------------------------------------------------------------------===//

let ParentPackage = TaintOptIn in {

def TaintedAllocChecker: Checker<"TaintedAlloc">,
HelpText<"Check for memory allocations, where the size parameter "
"might be a tainted (attacker controlled) value.">,
Dependencies<[DynamicMemoryModeling]>,
//FIXME: GenericTaintChecker should be a dependency, but only after it
//is transformed into a modeling checker
Documentation<HasDocumentation>;

} // end "optin.taint"

//===----------------------------------------------------------------------===//
// NonDeterminism checkers.
//===----------------------------------------------------------------------===//
Expand Down
22 changes: 16 additions & 6 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3080,12 +3080,22 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
}
}

// Return the value
if (VarT)
return this->emitRet(*VarT, VD);

// Return non-primitive values as pointers here.
return this->emitRet(PT_Ptr, VD);
// Return the value.
if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) {
// If the Ret above failed and this is a global variable, mark it as
// uninitialized, even everything else succeeded.
if (Context::shouldBeGloballyIndexed(VD)) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex);
Block *GlobalBlock = P.getGlobal(*GlobalIndex);
InlineDescriptor &ID =
*reinterpret_cast<InlineDescriptor *>(GlobalBlock->rawData());
ID.IsInitialized = false;
GlobalBlock->invokeDtor();
}
return false;
}
return true;
}

template <class Emitter>
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());

if (Res.isInvalid()) {
C.cleanup();
Stk.clear();
return false;
}
Expand All @@ -70,6 +71,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {

auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
C.cleanup();
Stk.clear();
return false;
}
Expand Down Expand Up @@ -97,6 +99,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
(VD->getType()->isRecordType() || VD->getType()->isArrayType());
auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
if (Res.isInvalid()) {
C.cleanup();
Stk.clear();
return false;
}
Expand Down
44 changes: 43 additions & 1 deletion clang/lib/AST/Interp/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//

#include "Boolean.h"
#include "Context.h"
#include "EvaluationResult.h"
#include "Floating.h"
#include "Function.h"
#include "FunctionPointer.h"
Expand Down Expand Up @@ -150,7 +152,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
}
Desc->dump(OS);
OS << "\n";
if (Desc->isPrimitive() && !Desc->isDummy()) {
if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
OS << " ";
{
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
Expand Down Expand Up @@ -305,3 +307,43 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
OS << " Extern: " << IsExtern << "\n";
OS << " Initialized: " << IsInitialized << "\n";
}

LLVM_DUMP_METHOD void EvaluationResult::dump() const {
assert(Ctx);
auto &OS = llvm::errs();
const ASTContext &ASTCtx = Ctx->getASTContext();

switch (Kind) {
case Empty:
OS << "Empty\n";
break;
case RValue:
OS << "RValue: ";
std::get<APValue>(Value).dump(OS, ASTCtx);
break;
case LValue: {
assert(Source);
QualType SourceType;
if (const auto *D = Source.dyn_cast<const Decl *>()) {
if (const auto *VD = dyn_cast<ValueDecl>(D))
SourceType = VD->getType();
} else if (const auto *E = Source.dyn_cast<const Expr *>()) {
SourceType = E->getType();
}

OS << "LValue: ";
if (const auto *P = std::get_if<Pointer>(&Value))
P->toAPValue().printPretty(OS, ASTCtx, SourceType);
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
FP->toAPValue().printPretty(OS, ASTCtx, SourceType);
OS << "\n";
break;
}
case Invalid:
OS << "Invalid\n";
break;
case Valid:
OS << "Valid\n";
break;
}
}
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ EvalEmitter::~EvalEmitter() {
}
}

/// Clean up all our resources. This needs to done in failed evaluations before
/// we call InterpStack::clear(), because there might be a Pointer on the stack
/// pointing into a Block in the EvalEmitter.
void EvalEmitter::cleanup() { S.cleanup(); }

EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
bool ConvertResultToRValue) {
S.setEvalLocation(E->getExprLoc());
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/EvalEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class EvalEmitter : public SourceMapper {
bool ConvertResultToRValue = false);
EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized);

/// Clean up all resources.
void cleanup();

InterpState &getState() { return S; }

protected:
Expand Down
41 changes: 0 additions & 41 deletions clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//

#include "EvaluationResult.h"
#include "Context.h"
#include "InterpState.h"
#include "Record.h"
#include "clang/AST/ExprCXX.h"
Expand Down Expand Up @@ -159,45 +158,5 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);
}

void EvaluationResult::dump() const {
assert(Ctx);
auto &OS = llvm::errs();
const ASTContext &ASTCtx = Ctx->getASTContext();

switch (Kind) {
case Empty:
OS << "Empty\n";
break;
case RValue:
OS << "RValue: ";
std::get<APValue>(Value).dump(OS, ASTCtx);
break;
case LValue: {
assert(Source);
QualType SourceType;
if (const auto *D = Source.dyn_cast<const Decl *>()) {
if (const auto *VD = dyn_cast<ValueDecl>(D))
SourceType = VD->getType();
} else if (const auto *E = Source.dyn_cast<const Expr *>()) {
SourceType = E->getType();
}

OS << "LValue: ";
if (const auto *P = std::get_if<Pointer>(&Value))
P->toAPValue().printPretty(OS, ASTCtx, SourceType);
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
FP->toAPValue().printPretty(OS, ASTCtx, SourceType);
OS << "\n";
break;
}
case Invalid:
OS << "Invalid\n";
break;
case Valid:
OS << "Valid\n";
break;
}
}

} // namespace interp
} // namespace clang
6 changes: 4 additions & 2 deletions clang/lib/AST/Interp/InterpBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,15 @@ class Block final {
void dump() const { dump(llvm::errs()); }
void dump(llvm::raw_ostream &OS) const;

protected:
private:
friend class Pointer;
friend class DeadBlock;
friend class InterpState;

Block(const Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
: IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
: IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {
assert(Desc);
}

/// Deletes a dead block at the end of its lifetime.
void cleanup();
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/InterpState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ InterpState::~InterpState() {
}
}

void InterpState::cleanup() {}

Frame *InterpState::getCurrentFrame() {
if (Current && Current->Caller)
return Current;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/InterpState.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class InterpState final : public State, public SourceMapper {

~InterpState();

void cleanup();

InterpState(const InterpState &) = delete;
InterpState &operator=(const InterpState &) = delete;

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class Program final {
// but primitive arrays might have an InitMap* heap allocated and
// that needs to be freed.
for (Global *G : Globals)
G->block()->invokeDtor();
if (Block *B = G->block(); B->isInitialized())
B->invokeDtor();

// Records might actually allocate memory themselves, but they
// are allocated using a BumpPtrAllocator. Call their desctructors
Expand Down
91 changes: 90 additions & 1 deletion clang/lib/AST/StmtOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "clang/AST/StmtOpenACC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtCXX.h"
using namespace clang;

OpenACCComputeConstruct *
Expand All @@ -26,11 +28,98 @@ OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
OpenACCComputeConstruct *OpenACCComputeConstruct::Create(
const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
SourceLocation DirLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock) {
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock,
ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs) {
void *Mem = C.Allocate(
OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
Clauses.size()));
auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc,
Clauses, StructuredBlock);

llvm::for_each(AssociatedLoopConstructs, [&](OpenACCLoopConstruct *C) {
C->setParentComputeConstruct(Inst);
});

return Inst;
}

void OpenACCComputeConstruct::findAndSetChildLoops() {
struct LoopConstructFinder : RecursiveASTVisitor<LoopConstructFinder> {
OpenACCComputeConstruct *Construct = nullptr;

LoopConstructFinder(OpenACCComputeConstruct *Construct)
: Construct(Construct) {}

bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) {
// Stop searching if we find a compute construct.
return true;
}
bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) {
// Stop searching if we find a loop construct, after taking ownership of
// it.
C->setParentComputeConstruct(Construct);
return true;
}
};

LoopConstructFinder f(this);
f.TraverseStmt(getAssociatedStmt());
}

OpenACCLoopConstruct::OpenACCLoopConstruct(unsigned NumClauses)
: OpenACCAssociatedStmtConstruct(
OpenACCLoopConstructClass, OpenACCDirectiveKind::Loop,
SourceLocation{}, SourceLocation{}, SourceLocation{},
/*AssociatedStmt=*/nullptr) {
std::uninitialized_value_construct(
getTrailingObjects<const OpenACCClause *>(),
getTrailingObjects<const OpenACCClause *>() + NumClauses);
setClauseList(
MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), NumClauses));
}

OpenACCLoopConstruct::OpenACCLoopConstruct(
SourceLocation Start, SourceLocation DirLoc, SourceLocation End,
ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop)
: OpenACCAssociatedStmtConstruct(OpenACCLoopConstructClass,
OpenACCDirectiveKind::Loop, Start, DirLoc,
End, Loop) {
// accept 'nullptr' for the loop. This is diagnosed somewhere, but this gives
// us some level of AST fidelity in the error case.
assert((Loop == nullptr || isa<ForStmt, CXXForRangeStmt>(Loop)) &&
"Associated Loop not a for loop?");
// Initialize the trailing storage.
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
getTrailingObjects<const OpenACCClause *>());

setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
Clauses.size()));
}

void OpenACCLoopConstruct::setLoop(Stmt *Loop) {
assert((isa<ForStmt, CXXForRangeStmt>(Loop)) &&
"Associated Loop not a for loop?");
setAssociatedStmt(Loop);
}

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

OpenACCLoopConstruct *
OpenACCLoopConstruct::Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation DirLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses,
Stmt *Loop) {
void *Mem =
C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>(
Clauses.size()));
auto *Inst =
new (Mem) OpenACCLoopConstruct(BeginLoc, DirLoc, EndLoc, Clauses, Loop);
return Inst;
}
13 changes: 13 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,19 @@ void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
PrintStmt(S->getStructuredBlock());
}

void StmtPrinter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) {
Indent() << "#pragma acc loop";

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

PrintStmt(S->getLoop());
}

//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2605,6 +2605,14 @@ void StmtProfiler::VisitOpenACCComputeConstruct(
P.VisitOpenACCClauseList(S->clauses());
}

void StmtProfiler::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) {
// VisitStmt handles children, so the Loop is handled.
VisitStmt(S);

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

void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
bool Canonical, bool ProfileLambdaExpr) const {
StmtProfilerWithPointers Profiler(ID, Context, Canonical, ProfileLambdaExpr);
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2869,3 +2869,10 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
}
void TextNodeDumper::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) {

if (S->isOrphanedLoopConstruct())
OS << " <orphan>";
else
OS << " parent: " << S->getParentComputeConstruct();
}
5 changes: 5 additions & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ static const CudaArchToStringMap arch_names[] = {
GFX(803), // gfx803
GFX(805), // gfx805
GFX(810), // gfx810
{CudaArch::GFX9_GENERIC, "gfx9-generic", "compute_amdgcn"},
GFX(900), // gfx900
GFX(902), // gfx902
GFX(904), // gfx903
Expand All @@ -122,23 +123,27 @@ static const CudaArchToStringMap arch_names[] = {
GFX(940), // gfx940
GFX(941), // gfx941
GFX(942), // gfx942
{CudaArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"},
GFX(1010), // gfx1010
GFX(1011), // gfx1011
GFX(1012), // gfx1012
GFX(1013), // gfx1013
{CudaArch::GFX10_3_GENERIC, "gfx10-3-generic", "compute_amdgcn"},
GFX(1030), // gfx1030
GFX(1031), // gfx1031
GFX(1032), // gfx1032
GFX(1033), // gfx1033
GFX(1034), // gfx1034
GFX(1035), // gfx1035
GFX(1036), // gfx1036
{CudaArch::GFX11_GENERIC, "gfx11-generic", "compute_amdgcn"},
GFX(1100), // gfx1100
GFX(1101), // gfx1101
GFX(1102), // gfx1102
GFX(1103), // gfx1103
GFX(1150), // gfx1150
GFX(1151), // gfx1151
{CudaArch::GFX12_GENERIC, "gfx12-generic", "compute_amdgcn"},
GFX(1200), // gfx1200
GFX(1201), // gfx1201
{CudaArch::Generic, "generic", ""},
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case CudaArch::GFX803:
case CudaArch::GFX805:
case CudaArch::GFX810:
case CudaArch::GFX9_GENERIC:
case CudaArch::GFX900:
case CudaArch::GFX902:
case CudaArch::GFX904:
Expand All @@ -207,23 +208,27 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case CudaArch::GFX940:
case CudaArch::GFX941:
case CudaArch::GFX942:
case CudaArch::GFX10_1_GENERIC:
case CudaArch::GFX1010:
case CudaArch::GFX1011:
case CudaArch::GFX1012:
case CudaArch::GFX1013:
case CudaArch::GFX10_3_GENERIC:
case CudaArch::GFX1030:
case CudaArch::GFX1031:
case CudaArch::GFX1032:
case CudaArch::GFX1033:
case CudaArch::GFX1034:
case CudaArch::GFX1035:
case CudaArch::GFX1036:
case CudaArch::GFX11_GENERIC:
case CudaArch::GFX1100:
case CudaArch::GFX1101:
case CudaArch::GFX1102:
case CudaArch::GFX1103:
case CudaArch::GFX1150:
case CudaArch::GFX1151:
case CudaArch::GFX12_GENERIC:
case CudaArch::GFX1200:
case CudaArch::GFX1201:
case CudaArch::Generic:
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,7 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(
case CudaArch::GFX803:
case CudaArch::GFX805:
case CudaArch::GFX810:
case CudaArch::GFX9_GENERIC:
case CudaArch::GFX900:
case CudaArch::GFX902:
case CudaArch::GFX904:
Expand All @@ -3516,23 +3517,27 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(
case CudaArch::GFX940:
case CudaArch::GFX941:
case CudaArch::GFX942:
case CudaArch::GFX10_1_GENERIC:
case CudaArch::GFX1010:
case CudaArch::GFX1011:
case CudaArch::GFX1012:
case CudaArch::GFX1013:
case CudaArch::GFX10_3_GENERIC:
case CudaArch::GFX1030:
case CudaArch::GFX1031:
case CudaArch::GFX1032:
case CudaArch::GFX1033:
case CudaArch::GFX1034:
case CudaArch::GFX1035:
case CudaArch::GFX1036:
case CudaArch::GFX11_GENERIC:
case CudaArch::GFX1100:
case CudaArch::GFX1101:
case CudaArch::GFX1102:
case CudaArch::GFX1103:
case CudaArch::GFX1150:
case CudaArch::GFX1151:
case CudaArch::GFX12_GENERIC:
case CudaArch::GFX1200:
case CudaArch::GFX1201:
case CudaArch::Generic:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OpenACCComputeConstructClass:
EmitOpenACCComputeConstruct(cast<OpenACCComputeConstruct>(*S));
break;
case Stmt::OpenACCLoopConstructClass:
EmitOpenACCLoopConstruct(cast<OpenACCLoopConstruct>(*S));
break;
}
}

Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4062,6 +4062,13 @@ class CodeGenFunction : public CodeGenTypeCache {
EmitStmt(S.getStructuredBlock());
}

void EmitOpenACCLoopConstruct(const OpenACCLoopConstruct &S) {
// TODO OpenACC: Implement this. It is currently implemented as a 'no-op',
// simply emitting its loop, but in the future we will implement
// some sort of IR.
EmitStmt(S.getLoop());
}

//===--------------------------------------------------------------------===//
// LValue Expression Emission
//===--------------------------------------------------------------------===//
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fopenmp");
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);

if (Args.hasArg(options::OPT_fopenmp_force_usm))
CmdArgs.push_back("-fopenmp-force-usm");

// FIXME: Clang supports a whole bunch more flags here.
break;
default:
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Driver/ToolChains/MSVC.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
/// formats, and to DWARF otherwise. Users can use -gcodeview and -gdwarf to
/// override the default.
llvm::codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
return getTriple().isOSBinFormatMachO()
? llvm::codegenoptions::DIF_DWARF
: llvm::codegenoptions::DIF_CodeView;
return getTriple().isOSBinFormatCOFF() ? llvm::codegenoptions::DIF_CodeView
: llvm::codegenoptions::DIF_DWARF;
}

/// Set the debugger tuning to "default", since we're definitely not tuning
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2407,6 +2407,9 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
// This option is automatically generated from UndefPrefixes.
if (Warning == "undef-prefix")
continue;
// This option is automatically generated from CheckConstexprFunctionBodies.
if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
continue;
Consumer(StringRef("-W") + Warning);
}

Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
case OpenACCDirectiveKind::Parallel:
case OpenACCDirectiveKind::Serial:
case OpenACCDirectiveKind::Kernels:
case OpenACCDirectiveKind::Loop:
return true;
}
llvm_unreachable("Unhandled directive->assoc stmt");
Expand Down Expand Up @@ -1447,13 +1448,14 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
return StmtError();

StmtResult AssocStmt;

SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(getActions().OpenACC(),
DirInfo.DirKind);
if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));

AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind,
ParseStatement());
AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(
DirInfo.StartLoc, DirInfo.DirKind, ParseStatement());
}

return getActions().OpenACC().ActOnEndStmtDirective(
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ add_clang_library(clangSema
Sema.cpp
SemaAMDGPU.cpp
SemaARM.cpp
SemaAVR.cpp
SemaAccess.cpp
SemaAttr.cpp
SemaAPINotes.cpp
Expand Down Expand Up @@ -58,12 +59,15 @@ add_clang_library(clangSema
SemaLambda.cpp
SemaLookup.cpp
SemaLoongArch.cpp
SemaM68k.cpp
SemaMIPS.cpp
SemaMSP430.cpp
SemaModule.cpp
SemaNVPTX.cpp
SemaObjC.cpp
SemaObjCProperty.cpp
SemaOpenACC.cpp
SemaOpenCL.cpp
SemaOpenMP.cpp
SemaOverload.cpp
SemaPPC.cpp
Expand All @@ -73,6 +77,7 @@ add_clang_library(clangSema
SemaStmtAsm.cpp
SemaStmtAttr.cpp
SemaSYCL.cpp
SemaSwift.cpp
SemaSystemZ.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaAVR.h"
#include "clang/Sema/SemaBPF.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
Expand All @@ -51,15 +52,19 @@
#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLoongArch.h"
#include "clang/Sema/SemaM68k.h"
#include "clang/Sema/SemaMIPS.h"
#include "clang/Sema/SemaMSP430.h"
#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
Expand Down Expand Up @@ -218,22 +223,27 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
CurScope(nullptr), Ident_super(nullptr),
AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
ARMPtr(std::make_unique<SemaARM>(*this)),
AVRPtr(std::make_unique<SemaAVR>(*this)),
BPFPtr(std::make_unique<SemaBPF>(*this)),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
HLSLPtr(std::make_unique<SemaHLSL>(*this)),
HexagonPtr(std::make_unique<SemaHexagon>(*this)),
LoongArchPtr(std::make_unique<SemaLoongArch>(*this)),
M68kPtr(std::make_unique<SemaM68k>(*this)),
MIPSPtr(std::make_unique<SemaMIPS>(*this)),
MSP430Ptr(std::make_unique<SemaMSP430>(*this)),
NVPTXPtr(std::make_unique<SemaNVPTX>(*this)),
ObjCPtr(std::make_unique<SemaObjC>(*this)),
OpenACCPtr(std::make_unique<SemaOpenACC>(*this)),
OpenCLPtr(std::make_unique<SemaOpenCL>(*this)),
OpenMPPtr(std::make_unique<SemaOpenMP>(*this)),
PPCPtr(std::make_unique<SemaPPC>(*this)),
PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)),
RISCVPtr(std::make_unique<SemaRISCV>(*this)),
SYCLPtr(std::make_unique<SemaSYCL>(*this)),
SwiftPtr(std::make_unique<SemaSwift>(*this)),
SystemZPtr(std::make_unique<SemaSystemZ>(*this)),
WasmPtr(std::make_unique<SemaWasm>(*this)),
X86Ptr(std::make_unique<SemaX86>(*this)),
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaSwift.h"

using namespace clang;

Expand Down Expand Up @@ -303,8 +304,8 @@ static void ProcessAPINotes(Sema &S, Decl *D,
SourceLocation(), nullptr, nullptr, nullptr,
ParsedAttr::Form::GNU());

if (!S.DiagnoseSwiftName(D, Info.SwiftName, D->getLocation(), *SNA,
/*IsAsync=*/false))
if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
/*IsAsync=*/false))
return nullptr;

return new (S.Context)
Expand Down
196 changes: 196 additions & 0 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"

namespace clang {
Expand Down Expand Up @@ -1085,4 +1086,199 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
}

namespace {
struct IntrinToName {
uint32_t Id;
int32_t FullName;
int32_t ShortName;
};
} // unnamed namespace

static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
ArrayRef<IntrinToName> Map,
const char *IntrinNames) {
AliasName.consume_front("__arm_");
const IntrinToName *It =
llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
return L.Id < Id;
});
if (It == Map.end() || It->Id != BuiltinID)
return false;
StringRef FullName(&IntrinNames[It->FullName]);
if (AliasName == FullName)
return true;
if (It->ShortName == -1)
return false;
StringRef ShortName(&IntrinNames[It->ShortName]);
return AliasName == ShortName;
}

bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_mve_builtin_aliases.inc"
// The included file defines:
// - ArrayRef<IntrinToName> Map
// - const char IntrinNames[]
return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}

bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_cde_builtin_aliases.inc"
return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}

bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
return BuiltinID >= AArch64::FirstSVEBuiltin &&
BuiltinID <= AArch64::LastSVEBuiltin;
}

bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
return BuiltinID >= AArch64::FirstSMEBuiltin &&
BuiltinID <= AArch64::LastSMEBuiltin;
}

void SemaARM::handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL) {
ASTContext &Context = getASTContext();
if (!AL.isArgIdent(0)) {
Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
<< AL << 1 << AANT_ArgumentIdentifier;
return;
}

IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
unsigned BuiltinID = Ident->getBuiltinID();
StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();

bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
!SmeAliasValid(BuiltinID, AliasName)) ||
(!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
!CdeAliasValid(BuiltinID, AliasName))) {
Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
return;
}

D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
}

static bool checkNewAttrMutualExclusion(
Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
FunctionType::ArmStateValue CurrentState, StringRef StateName) {
auto CheckForIncompatibleAttr =
[&](FunctionType::ArmStateValue IncompatibleState,
StringRef IncompatibleStateName) {
if (CurrentState == IncompatibleState) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
<< (std::string("'__arm_new(\"") + StateName.str() + "\")'")
<< (std::string("'") + IncompatibleStateName.str() + "(\"" +
StateName.str() + "\")'")
<< true;
AL.setInvalid();
}
};

CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
return AL.isInvalid();
}

void SemaARM::handleNewAttr(Decl *D, const ParsedAttr &AL) {
if (!AL.getNumArgs()) {
Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
AL.setInvalid();
return;
}

std::vector<StringRef> NewState;
if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
for (StringRef S : ExistingAttr->newArgs())
NewState.push_back(S);
}

bool HasZA = false;
bool HasZT0 = false;
for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
StringRef StateName;
SourceLocation LiteralLoc;
if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
return;

if (StateName == "za")
HasZA = true;
else if (StateName == "zt0")
HasZT0 = true;
else {
Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
AL.setInvalid();
return;
}

if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
NewState.push_back(StateName);
}

if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
FunctionType::ArmStateValue ZAState =
FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
if (HasZA && ZAState != FunctionType::ARM_None &&
checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
return;
FunctionType::ArmStateValue ZT0State =
FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
if (HasZT0 && ZT0State != FunctionType::ARM_None &&
checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
return;
}

D->dropAttr<ArmNewAttr>();
D->addAttr(::new (getASTContext()) ArmNewAttr(
getASTContext(), AL, NewState.data(), NewState.size()));
}

void SemaARM::handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL) {
if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
return;
}

const auto *FD = cast<FunctionDecl>(D);
if (!FD->isExternallyVisible()) {
Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
return;
}

D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
}

void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
if (AL.getNumArgs() > 1) {
Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
return;
}

StringRef Str;
SourceLocation ArgLoc;

if (AL.getNumArgs() == 0)
Str = "";
else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;

ARMInterruptAttr::InterruptType Kind;
if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
<< AL << Str << ArgLoc;
return;
}

D->addAttr(::new (getASTContext())
ARMInterruptAttr(getASTContext(), AL, Kind));
}

} // namespace clang
49 changes: 49 additions & 0 deletions clang/lib/Sema/SemaAVR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===------ SemaAVR.cpp ---------- AVR target-specific routines -----------===//
//
// 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 semantic analysis functions specific to AVR.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaAVR.h"
#include "clang/AST/DeclBase.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"

namespace clang {
SemaAVR::SemaAVR(Sema &S) : SemaBase(S) {}

void SemaAVR::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
if (!isFuncOrMethodForAttrSubject(D)) {
Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
return;
}

if (!AL.checkExactlyNumArgs(SemaRef, 0))
return;

handleSimpleAttribute<AVRInterruptAttr>(*this, D, AL);
}

void SemaAVR::handleSignalAttr(Decl *D, const ParsedAttr &AL) {
if (!isFuncOrMethodForAttrSubject(D)) {
Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
return;
}

if (!AL.checkExactlyNumArgs(SemaRef, 0))
return;

handleSimpleAttribute<AVRSignalAttr>(*this, D, AL);
}

} // namespace clang
20 changes: 20 additions & 0 deletions clang/lib/Sema/SemaBPF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/APSInt.h"
#include <optional>
Expand Down Expand Up @@ -171,4 +172,23 @@ bool SemaBPF::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
return false;
}

void SemaBPF::handlePreserveAIRecord(RecordDecl *RD) {
// Add preserve_access_index attribute to all fields and inner records.
for (auto *D : RD->decls()) {
if (D->hasAttr<BPFPreserveAccessIndexAttr>())
continue;

D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(getASTContext()));
if (auto *Rec = dyn_cast<RecordDecl>(D))
handlePreserveAIRecord(Rec);
}
}

void SemaBPF::handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL) {
auto *Rec = cast<RecordDecl>(D);
handlePreserveAIRecord(Rec);
Rec->addAttr(::new (getASTContext())
BPFPreserveAccessIndexAttr(getASTContext(), AL));
}

} // namespace clang
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLForwardCompat.h"
Expand Down Expand Up @@ -2918,7 +2919,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
} else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, *MA);
else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr))
NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName());
NewAttr = S.Swift().mergeNameAttr(D, *SNA, SNA->getName());
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
Expand Down
Loading