Skip to content

Commit

Permalink
merge internal development externally
Browse files Browse the repository at this point in the history
  • Loading branch information
searlmc1 committed May 3, 2024
2 parents 4390c8e + 0623fea commit 6e0007b
Show file tree
Hide file tree
Showing 106 changed files with 14,104 additions and 2,000 deletions.
4 changes: 4 additions & 0 deletions clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "../misc/StaticAssertCheck.h"
#include "../misc/ThrowByValueCatchByReferenceCheck.h"
#include "../performance/MoveConstructorInitCheck.h"
#include "../readability/EnumInitialValueCheck.h"
#include "../readability/UppercaseLiteralSuffixCheck.h"
#include "CommandProcessorCheck.h"
#include "DefaultOperatorNewAlignmentCheck.h"
Expand Down Expand Up @@ -299,6 +300,9 @@ class CERTModule : public ClangTidyModule {
"cert-flp37-c");
// FIO
CheckFactories.registerCheck<misc::NonCopyableObjectsCheck>("cert-fio38-c");
// INT
CheckFactories.registerCheck<readability::EnumInitialValueCheck>(
"cert-int09-c");
// MSC
CheckFactories.registerCheck<bugprone::UnsafeFunctionsCheck>(
"cert-msc24-c");
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ New checks
New check aliases
^^^^^^^^^^^^^^^^^

- New alias :doc:`cert-int09-c <clang-tidy/checks/cert/int09-c>` to
:doc:`readability-enum-initial-value <clang-tidy/checks/readability/enum-initial-value>`
was added.

Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/docs/clang-tidy/checks/cert/int09-c.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. title:: clang-tidy - cert-int09-c
.. meta::
:http-equiv=refresh: 5;URL=../readability/enum-initial-value.html

cert-int09-c
============

The `cert-int09-c` check is an alias, please see
:doc:`readability-enum-initial-value <../readability/enum-initial-value>` for
more information.
5 changes: 4 additions & 1 deletion clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,10 @@ Clang-Tidy Checks
:doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
:doc:`zircon-temporary-objects <zircon/temporary-objects>`,

Check aliases
-------------

.. csv-table:: Aliases..
.. csv-table::
:header: "Name", "Redirect", "Offers fixes"

:doc:`bugprone-narrowing-conversions <bugprone/narrowing-conversions>`, :doc:`cppcoreguidelines-narrowing-conversions <cppcoreguidelines/narrowing-conversions>`,
Expand All @@ -413,6 +415,7 @@ Clang-Tidy Checks
:doc:`cert-exp42-c <cert/exp42-c>`, :doc:`bugprone-suspicious-memory-comparison <bugprone/suspicious-memory-comparison>`,
:doc:`cert-fio38-c <cert/fio38-c>`, :doc:`misc-non-copyable-objects <misc/non-copyable-objects>`,
:doc:`cert-flp37-c <cert/flp37-c>`, :doc:`bugprone-suspicious-memory-comparison <bugprone/suspicious-memory-comparison>`,
:doc:`cert-int09-c <cert/int09-c>`, :doc:`readability-enum-initial-value <readability/enum-initial-value>`, "Yes"
:doc:`cert-msc24-c <cert/msc24-c>`, :doc:`bugprone-unsafe-functions <bugprone/unsafe-functions>`,
:doc:`cert-msc30-c <cert/msc30-c>`, :doc:`cert-msc50-cpp <cert/msc50-cpp>`,
:doc:`cert-msc32-c <cert/msc32-c>`, :doc:`cert-msc51-cpp <cert/msc51-cpp>`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,83 @@ readability-enum-initial-value
Enforces consistent style for enumerators' initialization, covering three
styles: none, first only, or all initialized explicitly.

When adding new enumerations, inconsistent initial value will cause potential
enumeration value conflicts.
An inconsistent style and strictness to defining the initializing value of
enumerators may cause issues if the enumeration is extended with new
enumerators that obtain their integer representation implicitly.

In an enumeration, the following three cases are accepted.
1. none of enumerators are explicit initialized.
2. the first enumerator is explicit initialized.
3. all of enumerators are explicit initialized.
The following three cases are accepted:

#. **No** enumerators are explicit initialized.
#. Exactly **the first** enumerator is explicit initialized.
#. **All** enumerators are explicit initialized.

.. code-block:: c++

// valid, none of enumerators are initialized.
enum A {
e0,
e1,
e2,
enum A { // (1) Valid, none of enumerators are initialized.
a0,
a1,
a2,
};

// valid, the first enumerator is initialized.
enum A {
e0 = 0,
e1,
e2,
enum B { // (2) Valid, the first enumerator is initialized.
b0 = 0,
b1,
b2,
};

// valid, all of enumerators are initialized.
enum A {
e0 = 0,
e1 = 1,
e2 = 2,
enum C { // (3) Valid, all of enumerators are initialized.
c0 = 0,
c1 = 1,
c2 = 2,
};

// invalid, e1 is not explicit initialized.
enum A {
enum D { // Invalid, d1 is not explicitly initialized!
d0 = 0,
d1,
d2 = 2,
};

enum E { // Invalid, e1, e3, and e5 are not explicitly initialized.
e0 = 0,
e1,
e2 = 2,
e3, // Dangerous, as the numeric values of e3 and e5 are both 3, and this is not explicitly visible in the code!
e4 = 2,
e5,
};

This check corresponds to the CERT C Coding Standard recommendation `INT09-C. Ensure enumeration constants map to unique values
<https://wiki.sei.cmu.edu/confluence/display/c/INT09-C.+Ensure+enumeration+constants+map+to+unique+values>`_.

`cert-int09-c` redirects here as an alias of this check.

Options
-------

.. option:: AllowExplicitZeroFirstInitialValue

If set to `false`, the first enumerator must not be explicitly initialized.
See examples below. Default is `true`.
If set to `false`, the first enumerator must not be explicitly initialized to
a literal ``0``.
Default is `true`.

.. code-block:: c++

enum A {
e0 = 0, // not allowed if AllowExplicitZeroFirstInitialValue is false
e1,
e2,
enum F {
f0 = 0, // Not allowed if AllowExplicitZeroFirstInitialValue is false.
f1,
f2,
};


.. option:: AllowExplicitSequentialInitialValues

If set to `false`, sequential initializations are not allowed.
See examples below. Default is `true`.
If set to `false`, explicit initialization to sequential values are not
allowed.
Default is `true`.

.. code-block:: c++

enum A {
e0 = 1, // not allowed if AllowExplicitSequentialInitialValues is false
e1 = 2,
e2 = 3,
};
enum G {
g0 = 1, // Not allowed if AllowExplicitSequentialInitialValues is false.
g1 = 2,
g2 = 3,
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ C++ Specific Potentially Breaking Changes
it's negative spelling can be used to obtain compatibility with previous
versions of clang.

- Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906).

ABI Changes in This Version
---------------------------
- Fixed Microsoft name mangling of implicitly defined variables used for thread
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 @@ -7511,6 +7511,9 @@ def err_nested_non_static_member_use : Error<
def warn_cxx98_compat_non_static_member_use : Warning<
"use of non-static data member %0 in an unevaluated context is "
"incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
def err_form_ptr_to_member_from_parenthesized_expr : Error<
"cannot form pointer to member from a parenthesized expression; "
"did you mean to remove the parentheses?">;
def err_invalid_incomplete_type_use : Error<
"invalid use of incomplete type %0">;
def err_builtin_func_cast_more_than_one_arg : Error<
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,14 @@ Descriptor::Descriptor(const DeclTy &D)
assert(Source && "Missing source");
}

/// Dummy array.
Descriptor::Descriptor(const DeclTy &D, UnknownSize)
: Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0),
AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
IsTemporary(false), IsArray(true), IsDummy(true) {
assert(Source && "Missing source");
}

QualType Descriptor::getType() const {
if (auto *E = asExpr())
return E->getType();
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/AST/Interp/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct Descriptor final {
/// Flag indicating if the block is an array.
const bool IsArray = false;
/// Flag indicating if this is a dummy descriptor.
bool IsDummy = false;
const bool IsDummy = false;

/// Storage management methods.
const BlockCtorFn CtorFn = nullptr;
Expand Down Expand Up @@ -162,8 +162,8 @@ struct Descriptor final {
/// Allocates a dummy descriptor.
Descriptor(const DeclTy &D);

/// Make this descriptor a dummy descriptor.
void makeDummy() { IsDummy = true; }
/// Allocates a dummy array descriptor.
Descriptor(const DeclTy &D, UnknownSize);

QualType getType() const;
QualType getElemQualType() const;
Expand Down
36 changes: 22 additions & 14 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -823,9 +823,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
// element in the same array are NOT equal. They have the same Base value,
// but a different Offset. This is a pretty rare case, so we fix this here
// by comparing pointers to the first elements.
if (!LHS.isZero() && LHS.isArrayRoot())
if (!LHS.isZero() && !LHS.isDummy() && LHS.isArrayRoot())
VL = LHS.atIndex(0).getByteOffset();
if (!RHS.isZero() && RHS.isArrayRoot())
if (!RHS.isZero() && !RHS.isDummy() && RHS.isArrayRoot())
VR = RHS.atIndex(0).getByteOffset();

S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
Expand Down Expand Up @@ -1241,16 +1241,14 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
!CheckNull(S, OpPC, Ptr, CSK_Field))
return false;

if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
return false;

if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize())
return false;

if (CheckDummy(S, OpPC, Ptr)) {
if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
return false;
}
S.Stk.push<Pointer>(Ptr.atField(Off));
return true;
}
Expand Down Expand Up @@ -2036,6 +2034,11 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
if (!Ptr.isZero()) {
if (!CheckArray(S, OpPC, Ptr))
return false;

if (Ptr.isDummy()) {
S.Stk.push<Pointer>(Ptr);
return true;
}
}

if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
Expand All @@ -2052,6 +2055,11 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
if (!Ptr.isZero()) {
if (!CheckArray(S, OpPC, Ptr))
return false;

if (Ptr.isDummy()) {
S.Stk.push<Pointer>(Ptr);
return true;
}
}

if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
Expand Down Expand Up @@ -2105,12 +2113,12 @@ inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex, uint32_t
inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isZero()) {
if (Ptr.isZero() || Ptr.isDummy()) {
S.Stk.push<Pointer>(Ptr);
return true;
}

if (!Ptr.isUnknownSizeArray() || Ptr.isDummy()) {
if (!Ptr.isUnknownSizeArray()) {
S.Stk.push<Pointer>(Ptr.atIndex(0));
return true;
}
Expand Down
21 changes: 9 additions & 12 deletions clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,17 @@ std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {
if (auto It = DummyVariables.find(VD); It != DummyVariables.end())
return It->second;

// Create dummy descriptor.
// We create desriptors of 'array of unknown size' if the type is an array
// type _and_ the size isn't known (it's not a ConstantArrayType). If the size
// is known however, we create a regular dummy pointer.
Descriptor *Desc;
if (std::optional<PrimType> T = Ctx.classify(VD->getType()))
Desc = createDescriptor(VD, *T, std::nullopt, true, false);
if (const auto *AT = VD->getType()->getAsArrayTypeUnsafe();
AT && !isa<ConstantArrayType>(AT))
Desc = allocateDescriptor(VD, Descriptor::UnknownSize{});
else
Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true,
false);
if (!Desc)
Desc = allocateDescriptor(VD);

assert(Desc);
Desc->makeDummy();

assert(Desc->isDummy());

// Allocate a block for storage.
unsigned I = Globals.size();

Expand Down Expand Up @@ -313,7 +310,8 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
for (const FieldDecl *FD : RD->fields()) {
// Note that we DO create fields and descriptors
// for unnamed bitfields here, even though we later ignore
// them everywhere. That's so the FieldDecl's getFieldIndex() matches.
// them everywhere. That's because so the FieldDecl's
// getFieldIndex() matches.

// Reserve space for the field's descriptor and the offset.
BaseSize += align(sizeof(InlineDescriptor));
Expand Down Expand Up @@ -346,7 +344,6 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
Descriptor::MetadataSize MDSize,
bool IsConst, bool IsTemporary,
bool IsMutable, const Expr *Init) {

// Classes and structures.
if (const auto *RT = Ty->getAs<RecordType>()) {
if (const auto *Record = getOrCreateRecord(RT->getDecl()))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8263,7 +8263,7 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args,

std::vector<std::string> EHArgs =
Args.getAllArgValues(options::OPT__SLASH_EH);
for (auto EHVal : EHArgs) {
for (const auto &EHVal : EHArgs) {
for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
switch (EHVal[I]) {
case 'a':
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3201,10 +3201,11 @@ void UnwrappedLineParser::parseDoWhile() {
void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
nextToken();
unsigned OldLineLevel = Line->Level;
if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level;

if (LeftAlignLabel)
Line->Level = 0;
else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level;

if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
FormatTok->is(tok::l_brace)) {
Expand Down
Loading

0 comments on commit 6e0007b

Please sign in to comment.