8 changes: 4 additions & 4 deletions clang/bindings/python/clang/cindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ def name(self):

@classmethod
def from_id(cls, id):
if id >= len(cls._kinds) or cls._kinds[id] is None:
if id < 0 or id >= len(cls._kinds) or cls._kinds[id] is None:
raise ValueError("Unknown template argument kind %d" % id)
return cls._kinds[id]

Expand Down Expand Up @@ -1336,7 +1336,7 @@ def __repr__(self):
CursorKind.OMP_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(271)

# OpenMP teams distribute simd directive.
CursorKind.OMP_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(272)
CursorKind.OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE = CursorKind(272)

# OpenMP teams distribute parallel for simd directive.
CursorKind.OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE = CursorKind(273)
Expand Down Expand Up @@ -2215,7 +2215,7 @@ def name(self):

@staticmethod
def from_id(id):
if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]:
if id < 0 or id >= len(StorageClass._kinds) or not StorageClass._kinds[id]:
raise ValueError("Unknown storage class %d" % id)
return StorageClass._kinds[id]

Expand Down Expand Up @@ -2395,7 +2395,7 @@ def __repr__(self):
TypeKind.OCLRESERVEID = TypeKind(160)

TypeKind.OBJCOBJECT = TypeKind(161)
TypeKind.OBJCCLASS = TypeKind(162)
TypeKind.OBJCTYPEPARAM = TypeKind(162)
TypeKind.ATTRIBUTED = TypeKind(163)

TypeKind.OCLINTELSUBGROUPAVCMCEPAYLOAD = TypeKind(164)
Expand Down
47 changes: 47 additions & 0 deletions clang/bindings/python/tests/cindex/test_enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import unittest

from clang.cindex import (
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
AvailabilityKind,
AccessSpecifier,
TypeKind,
RefQualifierKind,
LinkageKind,
TLSKind,
StorageClass,
)


class TestCursorKind(unittest.TestCase):
enums = [
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
AvailabilityKind,
AccessSpecifier,
TypeKind,
RefQualifierKind,
LinkageKind,
TLSKind,
StorageClass,
]

def test_from_id(self):
"""Check that kinds can be constructed from valid IDs"""
for enum in self.enums:
self.assertEqual(enum.from_id(2), enum._kinds[2])
with self.assertRaises(ValueError):
enum.from_id(len(enum._kinds))
with self.assertRaises(ValueError):
enum.from_id(-1)

def test_unique_kinds(self):
"""Check that no kind name has been used multiple times"""
for enum in self.enums:
for id in range(len(enum._kinds)):
try:
enum.from_id(id).name
except ValueError:
pass
6 changes: 3 additions & 3 deletions clang/cmake/caches/Fuchsia-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,14 @@ if(FUCHSIA_SDK)
set(LLVM_RUNTIME_MULTILIB_hwasan+noexcept_TARGETS "aarch64-unknown-fuchsia;riscv64-unknown-fuchsia" CACHE STRING "")
endif()

foreach(target armv6m-unknown-eabi)
foreach(target armv6m-unknown-eabi;armv7m-unknown-eabi;armv8m-unknown-eabi)
list(APPEND BUILTIN_TARGETS "${target}")
set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Generic CACHE STRING "")
set(BUILTINS_${target}_CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "")
set(BUILTINS_${target}_CMAKE_SYSROOT "" CACHE STRING "")
set(BUILTINS_${target}_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
foreach(lang C;CXX;ASM)
set(BUILTINS_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mcpu=cortex-m0plus -mthumb" CACHE STRING "")
set(BUILTINS_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mthumb" CACHE STRING "")
endforeach()
foreach(type SHARED;MODULE;EXE)
set(BUILTINS_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
Expand All @@ -321,7 +321,7 @@ foreach(target armv6m-unknown-eabi)
set(RUNTIMES_${target}_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
set(RUNTIMES_${target}_CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY CACHE STRING "")
foreach(lang C;CXX;ASM)
set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mcpu=cortex-m0plus -mthumb" CACHE STRING "")
set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mthumb" CACHE STRING "")
endforeach()
foreach(type SHARED;MODULE;EXE)
set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
Expand Down
37 changes: 34 additions & 3 deletions clang/docs/APINotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ entries:

Name: MyFramework

:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions:
:Classes, Protocols, Tags, Typedefs, Globals, Enumerators, Functions, Namespaces:

Arrays of top-level declarations. Each entry in the array must have a
'Name' key with its Objective-C name. "Tags" refers to structs, enums, and
unions; "Enumerators" refers to enum cases.
'Name' key with its Objective-C or C++ name. "Tags" refers to structs,
C++ classes, enums, and unions; "Classes" refers to Objective-C classes;
"Enumerators" refers to enum cases.

::

Expand Down Expand Up @@ -157,6 +158,36 @@ declaration kind), all of which are optional:
- Class: NSBundle
SwiftName: Bundle

:SwiftImportAs:

For a class, possible values are ``owned`` (equivalent to
``SWIFT_SELF_CONTAINED``) or ``reference`` (equivalent to
``SWIFT_SHARED_REFERENCE``, also requires specifying ``SwiftReleaseOp`` and
``SwiftRetainOp``).

For a method, possible values are ``unsafe`` (equivalent
to ``SWIFT_RETURNS_INDEPENDENT_VALUE``) or ``computed_property`` (equivalent to
``SWIFT_COMPUTED_PROPERTY``).

::

Tags:
- Name: RefCountedStorage
SwiftImportAs: reference
SwiftReleaseOp: RCRelease
SwiftRetainOp: RCRetain

:SwiftCopyable:

Allows annotating a C++ class as non-copyable in Swift. Equivalent to
``SWIFT_NONCOPYABLE``, or to an explicit conformance ``: ~Copyable``.

::

Tags:
- Name: tzdb
SwiftCopyable: false

:Availability, AvailabilityMsg:

A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of
Expand Down
19 changes: 17 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ Clang Frontend Potentially Breaking Changes
- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``;
existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead.

Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
- Renamed ``CursorKind`` variant 272 from ``OMP_TEAMS_DISTRIBUTE_DIRECTIVE``
to ``OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE``. The previous name was incorrect, it was a duplicate
of variant 271.
- Renamed ``TypeKind`` variant 162 from ``OBJCCLASS`` to ``OBJCTYPEPARAM``.
The previous name was incorrect, it was a duplicate of variant 28.

What's New in Clang |release|?
==============================
Some of the major new features and improvements to Clang are listed
Expand Down Expand Up @@ -846,6 +854,7 @@ Bug Fixes to C++ Support
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -903,11 +912,13 @@ Arm and AArch64 Support
a feature modifier for -march and -mcpu as well as via target attributes
like ``target_version`` or ``target_clones``.
- Support has been added for the following processors (-mcpu identifiers in parenthesis):
* Arm Cortex-R52+ (cortex-r52plus).
* Arm Cortex-R82AE (cortex-r82ae).
* Arm Cortex-A78AE (cortex-a78ae).
* Arm Cortex-A520AE (cortex-a520ae).
* Arm Cortex-A720AE (cortex-a720ae).
* Arm Cortex-R82AE (cortex-r82ae).
* Arm Cortex-R52+ (cortex-r52plus).
* Arm Cortex-A725 (cortex-a725).
* Arm Cortex-X925 (cortex-x925).
* Arm Neoverse-N3 (neoverse-n3).
* Arm Neoverse-V3 (neoverse-v3).
* Arm Neoverse-V3AE (neoverse-v3ae).
Expand All @@ -918,6 +929,10 @@ Android Support
Windows Support
^^^^^^^^^^^^^^^

- The clang-cl ``/Ot`` compiler option ("optimize for speed", also implied by
``/O2``) now maps to clang's ``-O3`` optimizataztion level instead of ``-O2``.
Users who prefer the old behavior can use ``clang-cl /Ot /clang:-O2 ...``.

- Clang-cl now supports function targets with intrinsic headers. This allows
for runtime feature detection of intrinsics. Previously under clang-cl
``immintrin.h`` and similar intrinsic headers would only include the intrinsics
Expand Down
29 changes: 25 additions & 4 deletions clang/docs/SourceBasedCodeCoverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -484,10 +484,31 @@ MC/DC Instrumentation
---------------------

When instrumenting for Modified Condition/Decision Coverage (MC/DC) using the
clang option ``-fcoverage-mcdc``, users are limited to at most **six** leaf-level
conditions in a boolean expression. A warning will be generated for boolean
expressions that contain more than six, and they will not be instrumented for
MC/DC.
clang option ``-fcoverage-mcdc``, there are two hard limits.

The maximum number of terms is limited to 32767, which is practical for
handwritten expressions. To be more restrictive in order to enforce coding rules,
use ``-Xclang -fmcdc-max-conditions=n``. Expressions with exceeded condition
counts ``n`` will generate warnings and will be excluded in the MC/DC coverage.

The number of test vectors (the maximum number of possible combinations of
expressions) is limited to 2,147,483,646. In this case, approximately
256MiB (==2GiB/8) is used to record test vectors.

To reduce memory usage, users can limit the maximum number of test vectors per
expression with ``-Xclang -fmcdc-max-test-vectors=m``.
If the number of test vectors resulting from the analysis of an expression
exceeds ``m``, a warning will be issued and the expression will be excluded
from the MC/DC coverage.

The number of test vectors ``m``, for ``n`` terms in an expression, can be
``m <= 2^n`` in the theoretical worst case, but is usually much smaller.
In simple cases, such as expressions consisting of a sequence of single
operators, ``m == n+1``. For example, ``(a && b && c && d && e && f && g)``
requires 8 test vectors.

Expressions such as ``((a0 && b0) || (a1 && b1) || ...)`` can cause the
number of test vectors to increase exponentially.

Also, if a boolean expression is embedded in the nest of another boolean
expression but separated by a non-logical operator, this is also not supported.
Expand Down
5 changes: 3 additions & 2 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4632,12 +4632,13 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Ob0 Disable function inlining
/Ob1 Only inline functions which are (explicitly or implicitly) marked inline
/Ob2 Inline functions as deemed beneficial by the compiler
/Ob3 Same as /Ob2
/Od Disable optimization
/Og No effect
/Oi- Disable use of builtin functions
/Oi Enable use of builtin functions
/Os Optimize for size
/Ot Optimize for speed
/Os Optimize for size (like clang -Os)
/Ot Optimize for speed (like clang -O3)
/Ox Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead
/Oy- Disable frame pointer omission (x86 only, default)
/Oy Enable frame pointer omission (x86 only)
Expand Down
15 changes: 0 additions & 15 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2452,21 +2452,6 @@ Check for pointer subtractions on two pointers pointing to different memory chun
int d = &y - &x; // warn
}
.. _alpha-core-SizeofPtr:
alpha.core.SizeofPtr (C)
""""""""""""""""""""""""
Warn about unintended use of ``sizeof()`` on pointer expressions.
.. code-block:: c
struct s {};
int test(struct s *p) {
return sizeof(p);
// warn: sizeof(ptr) can produce an unexpected result
}
.. _alpha-core-StackAddressAsyncEscape:
alpha.core.StackAddressAsyncEscape (C)
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType DeducedType,
bool IsDependent) const;

private:
QualType getDeducedTemplateSpecializationTypeInternal(TemplateName Template,
QualType DeducedType,
bool IsDependent,
QualType Canon) const;

public:
/// Return the unique reference to the type for the specified TagDecl
/// (struct/union/class/enum) decl.
QualType getTagDeclType(const TagDecl *Decl) const;
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,9 @@ class TemplateName {
/// error.
void dump() const;

void Profile(llvm::FoldingSetNodeID &ID);
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddPointer(Storage.getOpaqueValue());
}

/// Retrieve the template name as a void pointer.
void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
Expand Down
11 changes: 4 additions & 7 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -6050,30 +6050,27 @@ class DeducedTemplateSpecializationType : public DeducedType,

DeducedTemplateSpecializationType(TemplateName Template,
QualType DeducedAsType,
bool IsDeducedAsDependent)
bool IsDeducedAsDependent, QualType Canon)
: DeducedType(DeducedTemplateSpecialization, DeducedAsType,
toTypeDependence(Template.getDependence()) |
(IsDeducedAsDependent
? TypeDependence::DependentInstantiation
: TypeDependence::None),
DeducedAsType.isNull() ? QualType(this, 0)
: DeducedAsType.getCanonicalType()),
Canon),
Template(Template) {}

public:
/// Retrieve the name of the template that we are deducing.
TemplateName getTemplateName() const { return Template;}

void Profile(llvm::FoldingSetNodeID &ID) {
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
}

static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
QualType Deduced, bool IsDependent) {
Template.Profile(ID);
QualType CanonicalType =
Deduced.isNull() ? Deduced : Deduced.getCanonicalType();
ID.AddPointer(CanonicalType.getAsOpaquePtr());
Deduced.Profile(ID);
ID.AddBoolean(IsDependent || Template.isDependent());
}

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
///< regions.
CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria.
VALUE_CODEGENOPT(MCDCMaxConds, 16, 32767) ///< MC/DC Maximum conditions.
VALUE_CODEGENOPT(MCDCMaxTVs, 32, 0x7FFFFFFE) ///< MC/DC Maximum test vectors.

/// If -fpcc-struct-return or -freg-struct-return is specified.
ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -809,4 +809,7 @@ def warn_android_unversioned_fallback : Warning<

def err_drv_triple_version_invalid : Error<
"version '%0' in target triple '%1' is invalid">;

def warn_missing_include_dirs : Warning<
"no such include directory: '%0'">, InGroup<MissingIncludeDirs>, DefaultIgnore;
}
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">;
def MissingBraces : DiagGroup<"missing-braces">;
def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
def : DiagGroup<"missing-include-dirs">;
def MissingIncludeDirs : DiagGroup<"missing-include-dirs">;
def MissingNoreturn : DiagGroup<"missing-noreturn">;
def MultiChar : DiagGroup<"multichar">;
def : DiagGroup<"nested-externs">;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -8779,6 +8779,9 @@ def err_typecheck_incomplete_type_not_modifiable_lvalue : Error<
def err_typecheck_lvalue_casts_not_supported : Error<
"assignment to cast is illegal, lvalue casts are not supported">;

def note_typecheck_add_deref_star_not_modifiable_lvalue : Note<
"add '*' to dereference it">;

def err_typecheck_duplicate_vector_components_not_mlvalue : Error<
"vector is not assignable (contains duplicate components)">;
def err_block_decl_ref_not_modifiable_lvalue : Error<
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
std::pair<FileID, unsigned> &ROffs) const;

/// \param Loc a source location in a loaded AST (of a PCH/Module file).
/// \returns a FileID uniquely identifies the AST of a loaded
/// module/PCH where `Loc` is at.
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const;

/// Determines whether the two decomposed source location is in the same TU.
bool isInTheSameTranslationUnitImpl(
const std::pair<FileID, unsigned> &LOffs,
Expand Down
16 changes: 13 additions & 3 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,14 @@ defm mcdc_coverage : BoolFOption<"coverage-mcdc",
"Enable MC/DC criteria when generating code coverage">,
NegFlag<SetFalse, [], [ClangOption], "Disable MC/DC coverage criteria">,
BothFlags<[], [ClangOption, CLOption]>>;
def fmcdc_max_conditions_EQ : Joined<["-"], "fmcdc-max-conditions=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of conditions in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxConds">, "32767">;
def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of test vectors in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxTVs">, "0x7FFFFFFE">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
Expand Down Expand Up @@ -8116,7 +8124,7 @@ def show_inst : Flag<["-"], "show-inst">,
def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">,
HelpText<"The string to embed in the Dwarf debug AT_producer record.">;

def defsym : Separate<["-"], "defsym">,
def defsym : Separate<["--"], "defsym">,
HelpText<"Define a value for a symbol">;

} // let Visibility = [CC1AsOption]
Expand Down Expand Up @@ -8262,6 +8270,8 @@ def : CLFlag<"Ob1">, Alias<_SLASH_O>, AliasArgs<["b1"]>,
HelpText<"Only inline functions explicitly or implicitly marked inline">;
def : CLFlag<"Ob2">, Alias<_SLASH_O>, AliasArgs<["b2"]>,
HelpText<"Inline functions as deemed beneficial by the compiler">;
def : CLFlag<"Ob3">, Alias<_SLASH_O>, AliasArgs<["b3"]>,
HelpText<"Same as /Ob2">;
def : CLFlag<"Od", [CLOption, DXCOption]>, Alias<_SLASH_O>, AliasArgs<["d"]>,
HelpText<"Disable optimization">;
def : CLFlag<"Og">, Alias<_SLASH_O>, AliasArgs<["g"]>,
Expand All @@ -8271,9 +8281,9 @@ def : CLFlag<"Oi">, Alias<_SLASH_O>, AliasArgs<["i"]>,
def : CLFlag<"Oi-">, Alias<_SLASH_O>, AliasArgs<["i-"]>,
HelpText<"Disable use of builtin functions">;
def : CLFlag<"Os">, Alias<_SLASH_O>, AliasArgs<["s"]>,
HelpText<"Optimize for size">;
HelpText<"Optimize for size (like clang -Os)">;
def : CLFlag<"Ot">, Alias<_SLASH_O>, AliasArgs<["t"]>,
HelpText<"Optimize for speed">;
HelpText<"Optimize for speed (like clang -O3)">;
def : CLFlag<"Ox">, Alias<_SLASH_O>, AliasArgs<["x"]>,
HelpText<"Deprecated (like /Og /Oi /Ot /Oy /Ob2); use /O2">;
def : CLFlag<"Oy">, Alias<_SLASH_O>, AliasArgs<["y"]>,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ class FrontendOptions {
std::string ProductName;

// Currently this is only used as part of the `-extract-api` action.
// A comma seperated list of files providing a list of APIs to
// A comma separated list of files providing a list of APIs to
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {

// Check if an internal declaration in zippered library has an
// external declaration for a different platform. This results
// in the symbol being in a "seperate" platform slice.
// in the symbol being in a "separate" platform slice.
bool shouldIgnoreInternalZipperedSymbol(const Record *R,
const SymbolContext &SymCtx) const;

Expand Down
52 changes: 47 additions & 5 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2883,11 +2883,41 @@ class Preprocessor {
/// otherwise.
SourceLocation CurrentSafeBufferOptOutStart; // It is used to report the start location of an never-closed region.

// An ordered sequence of "-Wunsafe-buffer-usage" opt-out regions in one
// translation unit. Each region is represented by a pair of start and end
// locations. A region is "open" if its' start and end locations are
// identical.
SmallVector<std::pair<SourceLocation, SourceLocation>, 8> SafeBufferOptOutMap;
using SafeBufferOptOutRegionsTy =
SmallVector<std::pair<SourceLocation, SourceLocation>, 16>;
// An ordered sequence of "-Wunsafe-buffer-usage" opt-out regions in this
// translation unit. Each region is represented by a pair of start and
// end locations.
SafeBufferOptOutRegionsTy SafeBufferOptOutMap;

// The "-Wunsafe-buffer-usage" opt-out regions in loaded ASTs. We use the
// following structure to manage them by their ASTs.
struct {
// A map from unique IDs to region maps of loaded ASTs. The ID identifies a
// loaded AST. See `SourceManager::getUniqueLoadedASTID`.
llvm::DenseMap<FileID, SafeBufferOptOutRegionsTy> LoadedRegions;

// Returns a reference to the safe buffer opt-out regions of the loaded
// AST where `Loc` belongs to. (Construct if absent)
SafeBufferOptOutRegionsTy &
findAndConsLoadedOptOutMap(SourceLocation Loc, SourceManager &SrcMgr) {
return LoadedRegions[SrcMgr.getUniqueLoadedASTFileID(Loc)];
}

// Returns a reference to the safe buffer opt-out regions of the loaded
// AST where `Loc` belongs to. (This const function returns nullptr if
// absent.)
const SafeBufferOptOutRegionsTy *
lookupLoadedOptOutMap(SourceLocation Loc,
const SourceManager &SrcMgr) const {
FileID FID = SrcMgr.getUniqueLoadedASTFileID(Loc);
auto Iter = LoadedRegions.find(FID);

if (Iter == LoadedRegions.end())
return nullptr;
return &Iter->getSecond();
}
} LoadedSafeBufferOptOutMap;

public:
/// \return true iff the given `Loc` is in a "-Wunsafe-buffer-usage" opt-out
Expand Down Expand Up @@ -2918,6 +2948,18 @@ class Preprocessor {
/// opt-out region
bool isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc);

/// \return a sequence of SourceLocations representing ordered opt-out regions
/// specified by
/// `\#pragma clang unsafe_buffer_usage begin/end`s of this translation unit.
SmallVector<SourceLocation, 64> serializeSafeBufferOptOutMap() const;

/// \param SrcLocSeqs a sequence of SourceLocations deserialized from a
/// record of code `PP_UNSAFE_BUFFER_USAGE`.
/// \return true iff the `Preprocessor` has been updated; false `Preprocessor`
/// is same as itself before the call.
bool setDeserializedSafeBufferOptOutMap(
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);

private:
/// Helper functions to forward lexing to the actual lexer. They all share the
/// same signature.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,9 @@ enum ASTRecordTypes {
/// Record code for lexical and visible block for delayed namespace in
/// reduced BMI.
DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD = 68,

/// Record code for \#pragma clang unsafe_buffer_usage begin/end
PP_UNSAFE_BUFFER_USAGE = 69,
};

/// Record types used within a source manager block.
Expand Down
4 changes: 0 additions & 4 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,6 @@ def PointerSubChecker : Checker<"PointerSub">,
"different memory chunks">,
Documentation<HasDocumentation>;

def SizeofPointerChecker : Checker<"SizeofPtr">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
Documentation<HasDocumentation>;

def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
HelpText<"Check for division by variable that is later compared against 0. "
"Either the comparison is useless or there is division by zero.">,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ class MemRegionManager {
/// associated element type, index, and super region.
const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
const SubRegion *superRegion,
ASTContext &Ctx);
const ASTContext &Ctx);

const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
const SubRegion *superRegion) {
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Testing/TestAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ struct TestInputs {
/// Keys are plain filenames ("foo.h"), values are file content.
llvm::StringMap<std::string> ExtraFiles = {};

/// Root of execution, all relative paths in Args/Files are resolved against
/// this.
std::string WorkingDir;

/// Filename to use for translation unit. A default will be used when empty.
std::string FileName;

Expand Down
25 changes: 19 additions & 6 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5925,11 +5925,9 @@ QualType ASTContext::getUnconstrainedType(QualType T) const {
return T;
}

/// Return the uniqued reference to the deduced template specialization type
/// which has been deduced to the given type, or to the canonical undeduced
/// such type, or the canonical deduced-but-dependent such type.
QualType ASTContext::getDeducedTemplateSpecializationType(
TemplateName Template, QualType DeducedType, bool IsDependent) const {
QualType ASTContext::getDeducedTemplateSpecializationTypeInternal(
TemplateName Template, QualType DeducedType, bool IsDependent,
QualType Canon) const {
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
Expand All @@ -5940,7 +5938,8 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
return QualType(DTST, 0);

auto *DTST = new (*this, alignof(DeducedTemplateSpecializationType))
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent);
DeducedTemplateSpecializationType(Template, DeducedType, IsDependent,
Canon);
llvm::FoldingSetNodeID TempID;
DTST->Profile(TempID);
assert(ID == TempID && "ID does not match");
Expand All @@ -5949,6 +5948,20 @@ QualType ASTContext::getDeducedTemplateSpecializationType(
return QualType(DTST, 0);
}

/// Return the uniqued reference to the deduced template specialization type
/// which has been deduced to the given type, or to the canonical undeduced
/// such type, or the canonical deduced-but-dependent such type.
QualType ASTContext::getDeducedTemplateSpecializationType(
TemplateName Template, QualType DeducedType, bool IsDependent) const {
QualType Canon = DeducedType.isNull()
? getDeducedTemplateSpecializationTypeInternal(
getCanonicalTemplateName(Template), QualType(),
IsDependent, QualType())
: DeducedType.getCanonicalType();
return getDeducedTemplateSpecializationTypeInternal(Template, DeducedType,
IsDependent, Canon);
}

/// getAtomicType - Return the uniqued reference to the atomic type for
/// the given value type.
QualType ASTContext::getAtomicType(QualType T) const {
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/AST/ASTStructuralEquivalence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,15 @@ class StmtComparer {
return true;
}

bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
const CXXDependentScopeMemberExpr *E2) {
if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) {
return false;
}
return IsStructurallyEquivalent(Context, E1->getBaseType(),
E2->getBaseType());
}

bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1,
const UnaryExprOrTypeTraitExpr *E2) {
if (E1->getKind() != E2->getKind())
Expand Down Expand Up @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
return false;
}

if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
return false;
if (D1->getIndex() != D2->getIndex())
return false;
// Check types.
if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
if (Context.Complain) {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14014,8 +14014,8 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
QualType Ty = E->getTypeOfArgument();
// If the vector has a fixed size, we can determine the number of elements
// at compile time.
if (Ty->isVectorType())
return Success(Ty->castAs<VectorType>()->getNumElements(), E);
if (const auto *VT = Ty->getAs<VectorType>())
return Success(VT->getNumElements(), E);

assert(Ty->isSizelessVectorType());
if (Info.InConstantContext)
Expand Down
43 changes: 38 additions & 5 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
}

case CK_IntegralToBoolean:
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
if (DiscardResult)
return this->discard(SubExpr);
Expand All @@ -362,7 +363,12 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {

if (FromT == ToT)
return true;
return this->emitCast(*FromT, *ToT, CE);
if (!this->emitCast(*FromT, *ToT, CE))
return false;

if (CE->getCastKind() == CK_BooleanToSignedIntegral)
return this->emitNeg(*ToT, CE);
return true;
}

case CK_PointerToBoolean:
Expand Down Expand Up @@ -1201,6 +1207,23 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
}

if (T->isArrayType()) {
// Prepare composite return value.
if (!Initializing) {
if (GlobalDecl) {
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
if (!GlobalIndex)
return false;
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
return false;
} else {
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
}
}

unsigned ElementIndex = 0;
for (const Expr *Init : Inits) {
if (!this->visitArrayElemInit(ElementIndex, Init))
Expand Down Expand Up @@ -3223,6 +3246,8 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
else if (Val.isFloat())
return this->emitConstFloat(Val.getFloat(), E);

if (Val.isLValue()) {
if (Val.isNullPointer())
Expand Down Expand Up @@ -3253,7 +3278,7 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
const APValue &F = Val.getStructField(I);
const Record::Field *RF = R->getField(I);

if (F.isInt() || F.isLValue() || F.isMemberPointer()) {
if (F.isInt() || F.isFloat() || F.isLValue() || F.isMemberPointer()) {
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
Expand Down Expand Up @@ -3946,9 +3971,17 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
// we haven't seen yet.
if (Ctx.getLangOpts().CPlusPlus) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
const auto typeShouldBeVisited = [&](QualType T) -> bool {
if (T.isConstant(Ctx.getASTContext()))
return true;
if (const auto *RT = T->getAs<ReferenceType>())
return RT->getPointeeType().isConstQualified();
return false;
};

// Visit local const variables like normal.
if ((VD->isLocalVarDecl() || VD->isStaticDataMember()) &&
VD->getType().isConstQualified()) {
typeShouldBeVisited(VD->getType())) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
Expand All @@ -3957,8 +3990,8 @@ bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
VD && VD->getAnyInitializer() && VD->getType().isConstQualified() &&
!VD->isWeak()) {
VD && VD->getAnyInitializer() &&
VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak()) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) {
case APFloat::S_FloatTF32:
case APFloat::S_Float6E3M2FN:
case APFloat::S_Float6E2M3FN:
case APFloat::S_Float4E2M1FN:
llvm_unreachable("Tried to mangle unexpected APFloat semantics");
}

Expand Down
9 changes: 0 additions & 9 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,6 @@ bool TemplateName::containsUnexpandedParameterPack() const {
return getDependence() & TemplateNameDependence::UnexpandedPack;
}

void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
if (const auto* USD = getAsUsingShadowDecl())
ID.AddPointer(USD->getCanonicalDecl());
else if (const auto *TD = getAsTemplateDecl())
ID.AddPointer(TD->getCanonicalDecl());
else
ID.AddPointer(Storage.getOpaqueValue());
}

void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Qualified Qual) const {
auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) {
llvm::raw_svector_ostream SS(Str);
TN.print(SS, PrintPolicy);
}
OS << " '" << Str << "'";
OS << "'" << Str << "'";

if (Context) {
if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN);
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Basic/SourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,24 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
return DecompLoc;
}

FileID SourceManager::getUniqueLoadedASTFileID(SourceLocation Loc) const {
assert(isLoadedSourceLocation(Loc) &&
"Must be a source location in a loaded PCH/Module file");

auto [FID, Ignore] = getDecomposedLoc(Loc);
// `LoadedSLocEntryAllocBegin` stores the sorted lowest FID of each loaded
// allocation. Later allocations have lower FileIDs. The call below is to find
// the lowest FID of a loaded allocation from any FID in the same allocation.
// The lowest FID is used to identify a loaded allocation.
const FileID *FirstFID =
llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});

assert(FirstFID &&
"The failure to find the first FileID of a "
"loaded AST from a loaded source location was unexpected.");
return *FirstFID;
}

bool SourceManager::isInTheSameTranslationUnitImpl(
const std::pair<FileID, unsigned> &LOffs,
const std::pair<FileID, unsigned> &ROffs) const {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/OSTargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
public:
FuchsiaTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WIntType = TargetInfo::UnsignedInt;
this->MCountName = "__mcount";
this->TheCXXABI.set(TargetCXXABI::Fuchsia);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5760,7 +5760,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Add metadata if calling an __attribute__((error(""))) or warning fn.
if (TargetDecl && TargetDecl->hasAttr<ErrorAttr>()) {
llvm::ConstantInt *Line =
llvm::ConstantInt::get(Int32Ty, Loc.getRawEncoding());
llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding());
llvm::ConstantAsMetadata *MD = llvm::ConstantAsMetadata::get(Line);
llvm::MDTuple *MDT = llvm::MDNode::get(getLLVMContext(), {MD});
CI->setMetadata("srcloc", MDT);
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/CGCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {

assert(rv.isAggregate());
Address V = rv.getAggregateAddress();
return saved_type(
DominatingValue<Address>::save(CGF, V), rv.isVolatileQualified(),
DominatingValue<Address>::needsSaving(V) ? AggregateAddress
: AggregateLiteral);
return saved_type(DominatingValue<Address>::save(CGF, V),
DominatingValue<Address>::needsSaving(V)
? AggregateAddress
: AggregateLiteral);
}

/// Given a saved r-value produced by SaveRValue, perform the code
Expand All @@ -65,7 +65,7 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
case AggregateLiteral:
case AggregateAddress:
return RValue::getAggregate(
DominatingValue<Address>::restore(CGF, AggregateAddr), IsVolatile);
DominatingValue<Address>::restore(CGF, AggregateAddr));
case ComplexAddress: {
llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first);
llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second);
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ template <> struct DominatingValue<RValue> {
};
LLVM_PREFERRED_TYPE(Kind)
unsigned K : 3;
unsigned IsVolatile : 1;

saved_type(DominatingLLVMValue::saved_type Val1, unsigned K)
: Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {}
Expand All @@ -230,8 +229,7 @@ template <> struct DominatingValue<RValue> {
DominatingLLVMValue::saved_type Val2)
: Vals{Val1, Val2}, K(ComplexAddress) {}

saved_type(DominatingValue<Address>::saved_type AggregateAddr,
bool IsVolatile, unsigned K)
saved_type(DominatingValue<Address>::saved_type AggregateAddr, unsigned K)
: AggregateAddr(AggregateAddr), K(K) {}

public:
Expand Down
50 changes: 27 additions & 23 deletions clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,6 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
PGOHash Hash;
/// The map of statements to counters.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
/// The next bitmap byte index to assign.
unsigned NextMCDCBitmapIdx;
/// The state of MC/DC Coverage in this function.
MCDC::State &MCDCState;
/// Maximum number of supported MC/DC conditions in a boolean expression.
Expand All @@ -183,7 +181,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
MCDC::State &MCDCState, unsigned MCDCMaxCond,
DiagnosticsEngine &Diag)
: NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
NextMCDCBitmapIdx(0), MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
ProfileVersion(ProfileVersion), Diag(Diag) {}

// Blocks and lambdas are handled as separate functions, so we need not
Expand Down Expand Up @@ -314,11 +312,8 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true;
}

// Otherwise, allocate the number of bytes required for the bitmap
// based on the number of conditions. Must be at least 1-byte long.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = NextMCDCBitmapIdx;
unsigned SizeInBits = std::max<unsigned>(1L << NumCond, CHAR_BIT);
NextMCDCBitmapIdx += SizeInBits / CHAR_BIT;
// Otherwise, allocate the Decision.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = 0;
}
return true;
}
Expand Down Expand Up @@ -1083,7 +1078,9 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
// for most embedded applications. Setting a maximum value prevents the
// bitmap footprint from growing too large without the user's knowledge. In
// the future, this value could be adjusted with a command-line option.
unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 6 : 0;
unsigned MCDCMaxConditions =
(CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
: 0);

RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
RegionMCDCState.reset(new MCDC::State);
Expand All @@ -1099,7 +1096,6 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
NumRegionCounters = Walker.NextCounter;
RegionMCDCState->BitmapBytes = Walker.NextMCDCBitmapIdx;
FunctionHash = Walker.Hash.finalize();
}

Expand Down Expand Up @@ -1232,7 +1228,7 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) {
// anything.
llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes)};
Builder.getInt32(RegionMCDCState->BitmapBits)};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
}
Expand All @@ -1250,6 +1246,11 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
return;

// Don't create tvbitmap_update if the record is allocated but excluded.
// Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap.
if (DecisionStateIter->second.Indices.size() == 0)
return;

// Extract the offset of the global bitmap associated with this expression.
unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
Expand All @@ -1261,7 +1262,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
// index represents an executed test vector.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes),
Builder.getInt32(0), // Unused
Builder.getInt32(MCDCTestVectorBitmapOffset),
MCDCCondBitmapAddr.emitRawPointer(CGF)};
Builder.CreateCall(
Expand Down Expand Up @@ -1305,19 +1306,22 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
// Extract the ID of the condition we are setting in the bitmap.
const auto &Branch = BranchStateIter->second;
assert(Branch.ID >= 0 && "Condition has no ID!");
assert(Branch.DecisionStmt);

auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
// Cancel the emission if the Decision is erased after the allocation.
const auto DecisionIter =
RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
return;

// Emit intrinsic that updates a dedicated temporary value on the stack after
// a condition is evaluated. After the set of conditions has been updated,
// the resulting value is used to update the boolean expression's bitmap.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(Branch.ID),
MCDCCondBitmapAddr.emitRawPointer(CGF), Val};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update),
Args);
const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];

auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
"mcdc." + Twine(Branch.ID + 1) + ".cur");
auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[true]));
NewTV = Builder.CreateSelect(
Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[false])));
Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
}

void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
Expand Down
77 changes: 72 additions & 5 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ class SourceMappingRegion {
return std::holds_alternative<mcdc::BranchParameters>(MCDCParams);
}

const auto &getMCDCBranchParams() const {
return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
}

bool isMCDCDecision() const {
return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
}
Expand All @@ -204,6 +208,8 @@ class SourceMappingRegion {
}

const mcdc::Parameters &getMCDCParams() const { return MCDCParams; }

void resetMCDCParams() { MCDCParams = mcdc::Parameters(); }
};

/// Spelling locations for the start and end of a source region.
Expand Down Expand Up @@ -748,6 +754,7 @@ struct MCDCCoverageBuilder {

llvm::SmallVector<mcdc::ConditionIDs> DecisionStack;
MCDC::State &MCDCState;
const Stmt *DecisionStmt = nullptr;
mcdc::ConditionID NextID = 0;
bool NotMapped = false;

Expand Down Expand Up @@ -777,7 +784,8 @@ struct MCDCCoverageBuilder {

/// Set the given condition's ID.
void setCondID(const Expr *Cond, mcdc::ConditionID ID) {
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)].ID = ID;
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)] = {ID,
DecisionStmt};
}

/// Return the ID of a given condition.
Expand Down Expand Up @@ -808,6 +816,11 @@ struct MCDCCoverageBuilder {
if (NotMapped)
return;

if (NextID == 0) {
DecisionStmt = E;
assert(MCDCState.DecisionByStmt.contains(E));
}

const mcdc::ConditionIDs &ParentDecision = DecisionStack.back();

// If the operator itself has an assigned ID, this means it represents a
Expand Down Expand Up @@ -2122,20 +2135,70 @@ struct CounterCoverageMappingBuilder
subtractCounters(ParentCount, TrueCount));
}

void createDecision(const BinaryOperator *E) {
void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
if (NumConds == 0)
return;

// Extract [ID, Conds] to construct the graph.
llvm::SmallVector<mcdc::ConditionIDs> CondIDs(NumConds);
for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
if (SR.isMCDCBranch()) {
auto [ID, Conds] = SR.getMCDCBranchParams();
CondIDs[ID] = Conds;
}
}

// Construct the graph and calculate `Indices`.
mcdc::TVIdxBuilder Builder(CondIDs);
unsigned NumTVs = Builder.NumTestVectors;
unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);

if (NumTVs > MaxTVs) {
// NumTVs exceeds MaxTVs -- warn and cancel the Decision.
cancelDecision(E, Since, NumTVs, MaxTVs);
return;
}

// Update the state for CodeGenPGO
assert(MCDCState.DecisionByStmt.contains(E));
MCDCState.DecisionByStmt[E] = {
MCDCState.BitmapBits, // Top
std::move(Builder.Indices),
};

auto DecisionParams = mcdc::DecisionParameters{
MCDCState.DecisionByStmt[E].BitmapIdx,
MCDCState.BitmapBits += NumTVs, // Tail
NumConds,
};

// Create MCDC Decision Region.
createDecisionRegion(E, DecisionParams);
}

// Warn and cancel the Decision.
void cancelDecision(const BinaryOperator *E, unsigned Since, int NumTVs,
int MaxTVs) {
auto &Diag = CVM.getCodeGenModule().getDiags();
unsigned DiagID =
Diag.getCustomDiagID(DiagnosticsEngine::Warning,
"unsupported MC/DC boolean expression; "
"number of test vectors (%0) exceeds max (%1). "
"Expression will not be covered");
Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;

// Restore MCDCBranch to Branch.
for (auto &SR : MutableArrayRef(SourceRegions).slice(Since)) {
assert(!SR.isMCDCDecision() && "Decision shouldn't be seen here");
if (SR.isMCDCBranch())
SR.resetMCDCParams();
}

// Tell CodeGenPGO not to instrument.
MCDCState.DecisionByStmt.erase(E);
}

/// Check if E belongs to system headers.
bool isExprInSystemHeader(const BinaryOperator *E) const {
return (!SystemHeadersCoverage &&
Expand All @@ -2152,6 +2215,8 @@ struct CounterCoverageMappingBuilder

bool IsRootNode = MCDCBuilder.isIdle();

unsigned SourceRegionsSince = SourceRegions.size();

// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);

Expand Down Expand Up @@ -2190,7 +2255,7 @@ struct CounterCoverageMappingBuilder

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}

// Determine whether the right side of OR operation need to be visited.
Expand All @@ -2211,6 +2276,8 @@ struct CounterCoverageMappingBuilder

bool IsRootNode = MCDCBuilder.isIdle();

unsigned SourceRegionsSince = SourceRegions.size();

// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);

Expand Down Expand Up @@ -2253,7 +2320,7 @@ struct CounterCoverageMappingBuilder

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}

void VisitLambdaExpr(const LambdaExpr *LE) {
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CodeGen/MCDCState.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_CLANG_LIB_CODEGEN_MCDCSTATE_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ProfileData/Coverage/MCDCTypes.h"

namespace clang {
Expand All @@ -26,16 +27,18 @@ using namespace llvm::coverage::mcdc;

/// Per-Function MC/DC state
struct State {
unsigned BitmapBytes = 0;
unsigned BitmapBits = 0;

struct Decision {
unsigned BitmapIdx;
llvm::SmallVector<std::array<int, 2>> Indices;
};

llvm::DenseMap<const Stmt *, Decision> DecisionByStmt;

struct Branch {
ConditionID ID;
const Stmt *DecisionStmt;
};

llvm::DenseMap<const Stmt *, Branch> BranchByStmt;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,14 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (VFS->setCurrentWorkingDirectory(WD->getValue()))
Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();

// Check for missing include directories.
if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
if (!VFS->exists(IncludeDir))
Diag(diag::warn_missing_include_dirs) << IncludeDir;
}
}

// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2647,7 +2647,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
} else if (Value.starts_with("-mcpu") || Value.starts_with("-mfpu") ||
Value.starts_with("-mhwdiv") || Value.starts_with("-march")) {
// Do nothing, we'll validate it later.
} else if (Value == "-defsym") {
} else if (Value == "-defsym" || Value == "--defsym") {
if (A->getNumValues() != 2) {
D.Diag(diag::err_drv_defsym_invalid_format) << Value;
break;
Expand All @@ -2666,7 +2666,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
break;
}
CmdArgs.push_back(Value.data());
CmdArgs.push_back("--defsym");
TakeNextArg = true;
} else if (Value == "-fdebug-compilation-dir") {
CmdArgs.push_back("-fdebug-compilation-dir");
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,14 +1257,23 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
(isTargetIOSBased() && isIPhoneOSVersionLT(9)))
return 2;
return 4;
// Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.
if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||
(isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||
(isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||
(isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||
(isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||
(isTargetMacOSBased() &&
TargetVersion.empty())) // apple-darwin, no version.
return 4;
return 5;
}

void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
StringRef Component, RuntimeLinkOptions Opts,
bool IsShared) const {
SmallString<64> DarwinLibName = StringRef("libclang_rt.");
// an Darwin the builtins compomnent is not in the library name
// On Darwin the builtins component is not in the library name.
if (Component != "builtins") {
DarwinLibName += Component;
if (!(Opts & RLO_IsEmbedded))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Thread;
if (IsX86_64 || IsSystemZ)
if (IsX86_64 || IsSystemZ || IsPowerPC64)
Res |= SanitizerKind::KernelMemory;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
IsPowerPC64 || IsHexagon || IsLoongArch64 || IsRISCV64)
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
} else if (OptChar == '2' || OptChar == 'x') {
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "3");
}
if (SupportsForcingFramePointer &&
!DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
Expand All @@ -880,6 +880,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
break;
case '2':
case '3':
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
break;
}
Expand All @@ -901,7 +902,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
break;
case 't':
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "3");
break;
case 'y': {
bool OmitFramePointer = true;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2257,6 +2257,8 @@ bool UnwrappedLineParser::tryToParseLambda() {
break;
case tok::kw_auto:
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
case tok::kw_template:
case tok::kw_typename:
case tok::amp:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
if (isa<ParmVarDecl>(D))
return true;

// Skip variables in records. They are handled seperately for C++.
// Skip variables in records. They are handled separately for C++.
if (D->getDeclContext()->isRecord())
return true;

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Lex/HeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,8 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
using namespace llvm::sys;

llvm::SmallString<32> FilePath = File;
if (!WorkingDir.empty() && !path::is_absolute(FilePath))
fs::make_absolute(WorkingDir, FilePath);
// remove_dots switches to backslashes on windows as a side-effect!
// We always want to suggest forward slashes for includes.
// (not remove_dots(..., posix) as that misparses windows paths).
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2262,7 +2262,6 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
unsigned PrefixLen = 0;

while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen])) {
++PrefixLen;
if (!isLexingRawMode() &&
llvm::is_contained({'$', '@', '`'}, CurPtr[PrefixLen])) {
const char *Pos = &CurPtr[PrefixLen];
Expand All @@ -2271,6 +2270,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
: diag::ext_cxx26_raw_string_literal_character_set)
<< StringRef(Pos, 1);
}
++PrefixLen;
}

// If the last character was not a '(', then we didn't lex a valid delimiter.
Expand Down
110 changes: 91 additions & 19 deletions clang/lib/Lex/Preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
Expand Down Expand Up @@ -1483,26 +1484,56 @@ void Preprocessor::emitFinalMacroWarning(const Token &Identifier,
}

bool Preprocessor::isSafeBufferOptOut(const SourceManager &SourceMgr,
const SourceLocation &Loc) const {
// Try to find a region in `SafeBufferOptOutMap` where `Loc` is in:
auto FirstRegionEndingAfterLoc = llvm::partition_point(
SafeBufferOptOutMap,
[&SourceMgr,
&Loc](const std::pair<SourceLocation, SourceLocation> &Region) {
return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc);
});
const SourceLocation &Loc) const {
// The lambda that tests if a `Loc` is in an opt-out region given one opt-out
// region map:
auto TestInMap = [&SourceMgr](const SafeBufferOptOutRegionsTy &Map,
const SourceLocation &Loc) -> bool {
// Try to find a region in `SafeBufferOptOutMap` where `Loc` is in:
auto FirstRegionEndingAfterLoc = llvm::partition_point(
Map, [&SourceMgr,
&Loc](const std::pair<SourceLocation, SourceLocation> &Region) {
return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc);
});

if (FirstRegionEndingAfterLoc != Map.end()) {
// To test if the start location of the found region precedes `Loc`:
return SourceMgr.isBeforeInTranslationUnit(
FirstRegionEndingAfterLoc->first, Loc);
}
// If we do not find a region whose end location passes `Loc`, we want to
// check if the current region is still open:
if (!Map.empty() && Map.back().first == Map.back().second)
return SourceMgr.isBeforeInTranslationUnit(Map.back().first, Loc);
return false;
};

if (FirstRegionEndingAfterLoc != SafeBufferOptOutMap.end()) {
// To test if the start location of the found region precedes `Loc`:
return SourceMgr.isBeforeInTranslationUnit(FirstRegionEndingAfterLoc->first,
Loc);
}
// If we do not find a region whose end location passes `Loc`, we want to
// check if the current region is still open:
if (!SafeBufferOptOutMap.empty() &&
SafeBufferOptOutMap.back().first == SafeBufferOptOutMap.back().second)
return SourceMgr.isBeforeInTranslationUnit(SafeBufferOptOutMap.back().first,
Loc);
// What the following does:
//
// If `Loc` belongs to the local TU, we just look up `SafeBufferOptOutMap`.
// Otherwise, `Loc` is from a loaded AST. We look up the
// `LoadedSafeBufferOptOutMap` first to get the opt-out region map of the
// loaded AST where `Loc` is at. Then we find if `Loc` is in an opt-out
// region w.r.t. the region map. If the region map is absent, it means there
// is no opt-out pragma in that loaded AST.
//
// Opt-out pragmas in the local TU or a loaded AST is not visible to another
// one of them. That means if you put the pragmas around a `#include
// "module.h"`, where module.h is a module, it is not actually suppressing
// warnings in module.h. This is fine because warnings in module.h will be
// reported when module.h is compiled in isolation and nothing in module.h
// will be analyzed ever again. So you will not see warnings from the file
// that imports module.h anyway. And you can't even do the same thing for PCHs
// because they can only be included from the command line.

if (SourceMgr.isLocalSourceLocation(Loc))
return TestInMap(SafeBufferOptOutMap, Loc);

const SafeBufferOptOutRegionsTy *LoadedRegions =
LoadedSafeBufferOptOutMap.lookupLoadedOptOutMap(Loc, SourceMgr);

if (LoadedRegions)
return TestInMap(*LoadedRegions, Loc);
return false;
}

Expand Down Expand Up @@ -1551,6 +1582,47 @@ bool Preprocessor::isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc) {
return InSafeBufferOptOutRegion;
}

SmallVector<SourceLocation, 64>
Preprocessor::serializeSafeBufferOptOutMap() const {
assert(!InSafeBufferOptOutRegion &&
"Attempt to serialize safe buffer opt-out regions before file being "
"completely preprocessed");

SmallVector<SourceLocation, 64> SrcSeq;

for (const auto &[begin, end] : SafeBufferOptOutMap) {
SrcSeq.push_back(begin);
SrcSeq.push_back(end);
}
// Only `SafeBufferOptOutMap` gets serialized. No need to serialize
// `LoadedSafeBufferOptOutMap` because if this TU loads a pch/module, every
// pch/module in the pch-chain/module-DAG will be loaded one by one in order.
// It means that for each loading pch/module m, it just needs to load m's own
// `SafeBufferOptOutMap`.
return SrcSeq;
}

bool Preprocessor::setDeserializedSafeBufferOptOutMap(
const SmallVectorImpl<SourceLocation> &SourceLocations) {
if (SourceLocations.size() == 0)
return false;

assert(SourceLocations.size() % 2 == 0 &&
"ill-formed SourceLocation sequence");

auto It = SourceLocations.begin();
SafeBufferOptOutRegionsTy &Regions =
LoadedSafeBufferOptOutMap.findAndConsLoadedOptOutMap(*It, SourceMgr);

do {
SourceLocation Begin = *It++;
SourceLocation End = *It++;

Regions.emplace_back(Begin, End);
} while (It != SourceLocations.end());
return true;
}

ModuleLoader::~ModuleLoader() = default;

CommentHandler::~CommentHandler() = default;
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2093,16 +2093,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
}

// Don't allow SVE types in functions without a SVE target.
if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) {
if (Ty->isSVESizelessBuiltinType() && FD) {
llvm::StringMap<bool> CallerFeatureMap;
Context.getFunctionFeatureMap(CallerFeatureMap, FD);
if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty;
Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
else if (!IsArmStreamingFunction(FD,
/*IncludeLocallyStreaming=*/true)) {
Diag(D->getLocation(), diag::err_sve_vector_in_non_streaming_function)
<< Ty;
Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
}
}
}
Expand Down
24 changes: 22 additions & 2 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13288,6 +13288,23 @@ enum {
ConstUnknown, // Keep as last element
};

static void MaybeSuggestDerefFixIt(Sema &S, const Expr *E, SourceLocation Loc) {
ExprResult Deref;
Expr *TE = const_cast<Expr *>(E);
{
Sema::TentativeAnalysisScope Trap(S);
Deref = S.ActOnUnaryOp(S.getCurScope(), Loc, tok::star, TE);
}
if (Deref.isUsable() &&
Deref.get()->isModifiableLvalue(S.Context, &Loc) == Expr::MLV_Valid &&
!E->getType()->isObjCObjectPointerType()) {
S.Diag(E->getBeginLoc(),
diag::note_typecheck_add_deref_star_not_modifiable_lvalue)
<< E->getSourceRange()
<< FixItHint::CreateInsertion(E->getBeginLoc(), "*");
}
}

/// Emit the "read-only variable not assignable" error and print notes to give
/// more information about why the variable is not assignable, such as pointing
/// to the declaration of a const variable, showing that a method is const, or
Expand Down Expand Up @@ -13382,6 +13399,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< ExprRange << ConstVariable << VD << VD->getType();
MaybeSuggestDerefFixIt(S, E, Loc);
DiagnosticEmitted = true;
}
S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
Expand Down Expand Up @@ -13602,10 +13620,12 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
SourceRange Assign;
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
if (NeedType)
if (NeedType) {
S.Diag(Loc, DiagID) << E->getType() << E->getSourceRange() << Assign;
else
} else {
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
MaybeSuggestDerefFixIt(S, E, Loc);
}
return true;
}

Expand Down
22 changes: 18 additions & 4 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ class InitListChecker {
: InitListChecker(S, Entity, IL, T, /*VerifyOnly=*/true,
/*TreatUnavailableAsInvalid=*/false,
/*InOverloadResolution=*/false,
&AggrDeductionCandidateParamTypes){};
&AggrDeductionCandidateParamTypes) {}

bool HadError() { return hadError; }

Expand Down Expand Up @@ -1443,7 +1443,21 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// dependent non-array type or an array type with a value-dependent
// bound
assert(AggrDeductionCandidateParamTypes);
if (!isa_and_nonnull<ConstantArrayType>(

// In the presence of a braced-init-list within the initializer, we should
// not perform brace-elision, even if brace elision would otherwise be
// applicable. For example, given:
//
// template <class T> struct Foo {
// T t[2];
// };
//
// Foo t = {{1, 2}};
//
// we don't want the (T, T) but rather (T [2]) in terms of the initializer
// {{1, 2}}.
if (isa<InitListExpr, DesignatedInitExpr>(expr) ||
!isa_and_present<ConstantArrayType>(
SemaRef.Context.getAsArrayType(ElemType))) {
++Index;
AggrDeductionCandidateParamTypes->push_back(ElemType);
Expand Down Expand Up @@ -10940,14 +10954,14 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// if e_i is of array type and x_i is a braced-init-list, T_i is an
// rvalue reference to the declared type of e_i and
// C++ [over.match.class.deduct]p1.9:
// if e_i is of array type and x_i is a bstring-literal, T_i is an
// if e_i is of array type and x_i is a string-literal, T_i is an
// lvalue reference to the const-qualified declared type of e_i and
// C++ [over.match.class.deduct]p1.10:
// otherwise, T_i is the declared type of e_i
for (int I = 0, E = ListInit->getNumInits();
I < E && !isa<PackExpansionType>(ElementTypes[I]); ++I)
if (ElementTypes[I]->isArrayType()) {
if (isa<InitListExpr>(ListInit->getInit(I)))
if (isa<InitListExpr, DesignatedInitExpr>(ListInit->getInit(I)))
ElementTypes[I] = Context.getRValueReferenceType(ElementTypes[I]);
else if (isa<StringLiteral>(
ListInit->getInit(I)->IgnoreParenImpCasts()))
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1980,21 +1980,21 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
return false;

// There are no conversions between extended vector types, only identity.
if (ToType->isExtVectorType()) {
if (FromType->isExtVectorType()) {
if (auto *ToExtType = ToType->getAs<ExtVectorType>()) {
if (auto *FromExtType = FromType->getAs<ExtVectorType>()) {
// HLSL allows implicit truncation of vector types.
if (S.getLangOpts().HLSL) {
unsigned FromElts = FromType->getAs<VectorType>()->getNumElements();
unsigned ToElts = ToType->getAs<VectorType>()->getNumElements();
unsigned FromElts = FromExtType->getNumElements();
unsigned ToElts = ToExtType->getNumElements();
if (FromElts < ToElts)
return false;
if (FromElts == ToElts)
ICK = ICK_Identity;
else
ICK = ICK_HLSL_Vector_Truncation;

QualType FromElTy = FromType->getAs<VectorType>()->getElementType();
QualType ToElTy = ToType->getAs<VectorType>()->getElementType();
QualType FromElTy = FromExtType->getElementType();
QualType ToElTy = ToExtType->getElementType();
if (S.Context.hasSameUnqualifiedType(FromElTy, ToElTy))
return true;
return IsVectorElementConversion(S, FromElTy, ToElTy, ElConv, From);
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3583,6 +3583,17 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
break;
}

case PP_UNSAFE_BUFFER_USAGE: {
if (!Record.empty()) {
SmallVector<SourceLocation, 64> SrcLocs;
unsigned Idx = 0;
while (Idx < Record.size())
SrcLocs.push_back(ReadSourceLocation(F, Record, Idx));
PP.setDeserializedSafeBufferOptOutMap(SrcLocs);
}
break;
}

case PP_CONDITIONAL_STACK:
if (!Record.empty()) {
unsigned Idx = 0, End = Record.size() - 1;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(PP_CONDITIONAL_STACK);
RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);
RECORD(PP_ASSUME_NONNULL_LOC);
RECORD(PP_UNSAFE_BUFFER_USAGE);

// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
Expand Down Expand Up @@ -2518,6 +2519,12 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Record.clear();
}

// Write the safe buffer opt-out region map in PP
for (SourceLocation &S : PP.serializeSafeBufferOptOutMap())
AddSourceLocation(S, Record);
Stream.EmitRecord(PP_UNSAFE_BUFFER_USAGE, Record);
Record.clear();

// Enter the preprocessor block.
Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace clang {
unsigned AbbrevToUse;

/// A helper that can help us to write a packed bit across function
/// calls. For example, we may write seperate bits in seperate functions:
/// calls. For example, we may write separate bits in separate functions:
///
/// void VisitA(A* a) {
/// Record.push_back(a->isSomething());
Expand Down
1 change: 0 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ add_clang_library(clangStaticAnalyzerCheckers
CheckObjCInstMethSignature.cpp
CheckPlacementNew.cpp
CheckSecuritySyntaxOnly.cpp
CheckSizeofPointer.cpp
CheckerDocumentation.cpp
ChrootChecker.cpp
CloneChecker.cpp
Expand Down
96 changes: 0 additions & 96 deletions clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp

This file was deleted.

136 changes: 125 additions & 11 deletions clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,18 +717,56 @@ const ExplodedNode *StreamChecker::getAcquisitionSite(const ExplodedNode *N,
return nullptr;
}

static std::optional<int64_t> getKnownValue(ProgramStateRef State, SVal V) {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
if (const llvm::APSInt *Int = SVB.getKnownValue(State, V))
return Int->tryExtValue();
return std::nullopt;
}

/// Invalidate only the requested elements instead of the whole buffer.
/// This is basically a refinement of the more generic 'escapeArgs' or
/// the plain old 'invalidateRegions'.
static ProgramStateRef
escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
unsigned BlockCount, const SubRegion *Buffer,
QualType ElemType, int64_t StartIndex,
int64_t ElementCount) {
constexpr auto DoNotInvalidateSuperRegion =
RegionAndSymbolInvalidationTraits::InvalidationKinds::
TK_DoNotInvalidateSuperRegion;

const LocationContext *LCtx = Call.getLocationContext();
const ASTContext &Ctx = State->getStateManager().getContext();
SValBuilder &SVB = State->getStateManager().getSValBuilder();
auto &RegionManager = Buffer->getMemRegionManager();

SmallVector<SVal> EscapingVals;
EscapingVals.reserve(ElementCount);

RegionAndSymbolInvalidationTraits ITraits;
for (auto Idx : llvm::seq(StartIndex, StartIndex + ElementCount)) {
NonLoc Index = SVB.makeArrayIndex(Idx);
const auto *Element =
RegionManager.getElementRegion(ElemType, Index, Buffer, Ctx);
EscapingVals.push_back(loc::MemRegionVal(Element));
ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
}
return State->invalidateRegions(
EscapingVals, Call.getOriginExpr(), BlockCount, LCtx,
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
}

static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call,
ArrayRef<unsigned int> EscapingArgs) {
const auto *CE = Call.getOriginExpr();

SmallVector<SVal> EscapingVals;
EscapingVals.reserve(EscapingArgs.size());
for (auto EscArgIdx : EscapingArgs)
EscapingVals.push_back(Call.getArgSVal(EscArgIdx));
State = State->invalidateRegions(EscapingVals, CE, C.blockCount(),
C.getLocationContext(),
/*CausesPointerEscape=*/false);
auto GetArgSVal = [&Call](int Idx) { return Call.getArgSVal(Idx); };
auto EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
State = State->invalidateRegions(EscapingVals, Call.getOriginExpr(),
C.blockCount(), C.getLocationContext(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
return State;
}

Expand Down Expand Up @@ -907,6 +945,76 @@ void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call,
C.addTransition(State);
}

static std::optional<QualType> getPointeeType(const MemRegion *R) {
if (!R)
return std::nullopt;
if (const auto *ER = dyn_cast<ElementRegion>(R))
return ER->getElementType();
if (const auto *TR = dyn_cast<TypedValueRegion>(R))
return TR->getValueType();
if (const auto *SR = dyn_cast<SymbolicRegion>(R))
return SR->getPointeeStaticType();
return std::nullopt;
}

static std::optional<NonLoc> getStartIndex(SValBuilder &SVB,
const MemRegion *R) {
if (!R)
return std::nullopt;

auto Zero = [&SVB] {
BasicValueFactory &BVF = SVB.getBasicValueFactory();
return nonloc::ConcreteInt(BVF.getIntValue(0, /*isUnsigned=*/false));
};

if (const auto *ER = dyn_cast<ElementRegion>(R))
return ER->getIndex();
if (isa<TypedValueRegion>(R))
return Zero();
if (isa<SymbolicRegion>(R))
return Zero();
return std::nullopt;
}

static ProgramStateRef
tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call, NonLoc SizeVal,
NonLoc NMembVal) {
// Try to invalidate the individual elements.
const auto *Buffer =
dyn_cast_or_null<SubRegion>(Call.getArgSVal(0).getAsRegion());

std::optional<QualType> ElemTy = getPointeeType(Buffer);
std::optional<SVal> StartElementIndex =
getStartIndex(C.getSValBuilder(), Buffer);

// Drop the outermost ElementRegion to get the buffer.
if (const auto *ER = dyn_cast_or_null<ElementRegion>(Buffer))
Buffer = dyn_cast<SubRegion>(ER->getSuperRegion());

std::optional<int64_t> CountVal = getKnownValue(State, NMembVal);
std::optional<int64_t> Size = getKnownValue(State, SizeVal);
std::optional<int64_t> StartIndexVal =
getKnownValue(State, StartElementIndex.value_or(UnknownVal()));

if (ElemTy && CountVal && Size && StartIndexVal) {
int64_t NumBytesRead = Size.value() * CountVal.value();
int64_t ElemSizeInChars =
C.getASTContext().getTypeSizeInChars(*ElemTy).getQuantity();
bool IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0;
int64_t NumCompleteOrIncompleteElementsRead =
NumBytesRead / ElemSizeInChars + IncompleteLastElement;

constexpr int MaxInvalidatedElementsLimit = 64;
if (NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) {
return escapeByStartIndexAndCount(State, Call, C.blockCount(), Buffer,
*ElemTy, *StartIndexVal,
NumCompleteOrIncompleteElementsRead);
}
}
return nullptr;
}

void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
const CallEvent &Call, CheckerContext &C,
bool IsFread) const {
Expand Down Expand Up @@ -937,8 +1045,14 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,

// At read, invalidate the buffer in any case of error or success,
// except if EOF was already present.
if (IsFread && !E.isStreamEof())
State = escapeArgs(State, C, Call, {0});
if (IsFread && !E.isStreamEof()) {
// Try to invalidate the individual elements.
// Otherwise just fall back to invalidating the whole buffer.
ProgramStateRef InvalidatedState = tryToInvalidateFReadBufferByElements(
State, C, Call, *SizeVal, *NMembVal);
State =
InvalidatedState ? InvalidatedState : escapeArgs(State, C, Call, {0});
}

// Generate a transition for the success state.
// If we know the state to be FEOF at fread, do not add a success state.
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/StaticAnalyzer/Core/MemRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,10 +1155,10 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
return getSubRegion<CompoundLiteralRegion>(CL, sReg);
}

const ElementRegion*
const ElementRegion *
MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
const SubRegion* superRegion,
ASTContext &Ctx){
const SubRegion *superRegion,
const ASTContext &Ctx) {
QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();

llvm::FoldingSetNodeID ID;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Testing/TestAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Testing/CommandLineArgs.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VirtualFileSystem.h"

#include "gtest/gtest.h"
Expand Down Expand Up @@ -106,6 +107,8 @@ TestAST::TestAST(const TestInputs &In) {

// Set up a VFS with only the virtual file visible.
auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
if (auto Err = VFS->setCurrentWorkingDirectory(In.WorkingDir))
ADD_FAILURE() << "Failed to setWD: " << Err.message();
VFS->addFile(Filename, /*ModificationTime=*/0,
llvm::MemoryBuffer::getMemBufferCopy(In.Code, Filename));
for (const auto &Extra : In.ExtraFiles)
Expand Down
16 changes: 16 additions & 0 deletions clang/test/AST/Interp/cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ constexpr int preInc(int x) { // both-error {{never produces a constant expressi
constexpr int postInc(int x) { // both-error {{never produces a constant expression}}
return x++; // both-note {{subexpression}}
}


namespace ReferenceToConst {
template<int n> struct S; // both-note 1{{here}}
struct LiteralType {
constexpr LiteralType(int n) : n(n) {}
int n;
};
template<int n> struct T {
T() {
static const int ki = 42;
const int &i2 = ki;
typename S<i2>::T check5; // both-error {{undefined template}}
}
};
}
7 changes: 7 additions & 0 deletions clang/test/AST/Interp/opencl.cl
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ void negativeShift32(int a,int b) {

int2 A = {1,2};
int4 B = {(int2)(1,2), (int2)(3,4)};


constant int sz0 = 5;
kernel void testvla()
{
int vla0[sz0];
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,4 +1479,17 @@ namespace VirtOperator {
};
constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}}
}

namespace FloatAPValue {
struct ClassTemplateArg {
int a;
float f;
};
template<ClassTemplateArg A> struct ClassTemplateArgTemplate {
static constexpr const ClassTemplateArg &Arg = A;
};
ClassTemplateArgTemplate<ClassTemplateArg{1, 2.0f}> ClassTemplateArgObj;
template<const ClassTemplateArg&> struct ClassTemplateArgRefTemplate {};
ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj;
}
#endif
5 changes: 5 additions & 0 deletions clang/test/AST/Interp/references.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,8 @@ constexpr int RecordWithRef2() {
return r.a;
}
static_assert(RecordWithRef2() == 200, "");

const char (&nonextended_string_ref)[3] = {"hi"};
static_assert(nonextended_string_ref[0] == 'h', "");
static_assert(nonextended_string_ref[1] == 'i', "");
static_assert(nonextended_string_ref[2] == '\0', "");
9 changes: 9 additions & 0 deletions clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ namespace {
typedef float __attribute__((vector_size(16))) VI42;
constexpr VI42 A2 = A; // expected-error {{must be initialized by a constant expression}}
}

namespace BoolToSignedIntegralCast{
typedef __attribute__((__ext_vector_type__(4))) unsigned int int4;
constexpr int4 intsT = (int4)true;
static_assert(intsT[0] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[1] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[2] == -1, "");// ref-error {{not an integral constant expression}}
static_assert(intsT[3] == -1, "");// ref-error {{not an integral constant expression}}
}
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-ctad-alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ Out2<double>::AInner t(1.0);
// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2<double>::AInner' dependent
// CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
// CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
// CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}}
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<type-parameter-1-0>' sugar dependent
// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<type-parameter-1-0>' dependent
// CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
// CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
// CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}}
// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0'
Expand Down
6 changes: 3 additions & 3 deletions clang/test/AST/ast-dump-template-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ using type2 = typename C<int>::type1<void>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:42> col:7 type2 'typename C<int>::type1<void>':'void (int)'
// CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C<int>::type1<void>' sugar
// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1<void>' sugar alias
// CHECK-NEXT: name: 'C<int>::type1':'PR55886::C<int>::type1' qualified
// CHECK-NEXT: name: 'C<int>::type1':'PR55886::C<int>::type1' qualified
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'C<int>':'PR55886::C<int>'
// CHECK-NEXT: TypeAliasTemplateDecl {{.+}} type1
// CHECK-NEXT: TemplateArgument type 'void'
Expand Down Expand Up @@ -153,7 +153,7 @@ template <typename... T> struct D {
};
using t2 = D<float, char>::B<int, short>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias{{$}}
// CHECK-NEXT: name: 'D<float, char>::B':'PR56099::D<float, char>::B' qualified
// CHECK-NEXT: name: 'D<float, char>::B':'PR56099::D<float, char>::B' qualified
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
Expand All @@ -175,7 +175,7 @@ template<class E1, class E2> class E {};
using test1 = D<E, int>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
Expand Down
8 changes: 4 additions & 4 deletions clang/test/AST/ast-dump-using-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ using A = S<T>;
// CHECK: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S<T>' sugar dependent
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S<T>' dependent
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S'

// TemplateName in TemplateArgument.
Expand All @@ -30,7 +30,7 @@ using B = X<S>;
// CHECK: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType {{.*}} 'X<S>' sugar
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'X<S>' sugar
// CHECK-NEXT: |-name: 'X' qualified
// CHECK-NEXT: |-name: 'X' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} X
// CHECK-NEXT: |-TemplateArgument template 'S':'ns::S' qualified
// CHECK-NEXT: | |-UsingShadowDecl {{.*}} implicit ClassTemplate {{.*}} 'S'
Expand All @@ -45,7 +45,7 @@ using C = decltype(DeducedTemplateSpecializationT);
// CHECK-NEXT: |-DeclRefExpr {{.*}}
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S<int>' sugar
// CHECK-NEXT: `-DeducedTemplateSpecializationType {{.*}} 'ns::S<int>' sugar
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: |-name: 'S':'ns::S' qualified
// CHECK-NEXT: | |-UsingShadowDecl {{.+}} 'S'

S2 DeducedTemplateSpecializationT2(123);
Expand All @@ -54,5 +54,5 @@ using D = decltype(DeducedTemplateSpecializationT2);
// CHECK-NEXT: |-DeclRefExpr {{.*}}
// CHECK-NEXT: `-ElaboratedType {{.*}} 'S2<int>' sugar
// CHECK-NEXT: `-DeducedTemplateSpecializationType {{.*}} 'S2<int>' sugar
// CHECK-NEXT: |-name: 'S2':'ns::S2' qualified
// CHECK-NEXT: |-name: 'S2':'ns::S2' qualified
//CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S2'
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
// suppressed.
#pragma clang system_header

typedef __typeof(sizeof(int)) size_t;
typedef struct _FILE {
unsigned char *_p;
} FILE;
FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
int fputc(int, FILE *);
int fputs(const char *restrict, FILE *restrict) __asm("_" "fputs" );
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
int fgetc(FILE *stream);
int fclose(FILE *);
void exit(int);

Expand Down
Loading