[clang] [Clang][Sema] Fix missing warning when comparing mismatched enums in … (PR #81389)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 10 15:32:05 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (44-2-Kupa-Martin)
<details>
<summary>Changes</summary>
…C mode
Factored logic from `CheckImplicitConversion` into new methods `Expr::getEnumConstantDecl` and `Expr::getEnumCoercedType` for use in `checkEnumArithmeticConversions`.
Fix #<!-- -->29217
---
Patch is 650.51 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81389.diff
9 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+3)
- (modified) clang/include/clang/AST/Expr.h (+256-269)
- (modified) clang/lib/AST/Expr.cpp (+585-463)
- (modified) clang/lib/Sema/SemaChecking.cpp (+1428-1193)
- (modified) clang/lib/Sema/SemaExpr.cpp (+1534-1453)
- (modified) clang/test/Sema/builtins-elementwise-math.c (+4)
- (added) clang/test/Sema/warn-compare-enum-types-mismatch.c (+42)
- (renamed) clang/test/Sema/warn-conditional-enum-types-mismatch.c (+1-1)
- (modified) clang/test/Sema/warn-overlap.c (+2-2)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ece6013f672621..00ddf0b9656a31 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -161,6 +161,9 @@ Improvements to Clang's time-trace
Bug Fixes in This Version
-------------------------
+- Fixed missing warnings when comparing mismatched enumeration constants
+ in C (`#29217 <https://github.com/llvm/llvm-project/issues/29217>`).
+
- Clang now accepts elaborated-type-specifiers that explicitly specialize
a member class template for an implicit instantiation of a class template.
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 3fc481a62a78a9..4f11f3eb610564 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -40,26 +40,26 @@
#include <optional>
namespace clang {
- class APValue;
- class ASTContext;
- class BlockDecl;
- class CXXBaseSpecifier;
- class CXXMemberCallExpr;
- class CXXOperatorCallExpr;
- class CastExpr;
- class Decl;
- class IdentifierInfo;
- class MaterializeTemporaryExpr;
- class NamedDecl;
- class ObjCPropertyRefExpr;
- class OpaqueValueExpr;
- class ParmVarDecl;
- class StringLiteral;
- class TargetInfo;
- class ValueDecl;
+class APValue;
+class ASTContext;
+class BlockDecl;
+class CXXBaseSpecifier;
+class CXXMemberCallExpr;
+class CXXOperatorCallExpr;
+class CastExpr;
+class Decl;
+class IdentifierInfo;
+class MaterializeTemporaryExpr;
+class NamedDecl;
+class ObjCPropertyRefExpr;
+class OpaqueValueExpr;
+class ParmVarDecl;
+class StringLiteral;
+class TargetInfo;
+class ValueDecl;
/// A simple array of base specifiers.
-typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+typedef SmallVector<CXXBaseSpecifier *, 4> CXXCastPath;
/// An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
@@ -88,7 +88,7 @@ struct SubobjectAdjustment {
SubobjectAdjustment(const CastExpr *BasePath,
const CXXRecordDecl *DerivedClass)
- : Kind(DerivedToBaseAdjustment) {
+ : Kind(DerivedToBaseAdjustment) {
DerivedToBase.BasePath = BasePath;
DerivedToBase.DerivedClass = DerivedClass;
}
@@ -98,7 +98,7 @@ struct SubobjectAdjustment {
}
SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS)
- : Kind(MemberPointerAdjustment) {
+ : Kind(MemberPointerAdjustment) {
this->Ptr.MPT = MPT;
this->Ptr.RHS = RHS;
}
@@ -112,10 +112,10 @@ class Expr : public ValueStmt {
public:
Expr() = delete;
- Expr(const Expr&) = delete;
+ Expr(const Expr &) = delete;
Expr(Expr &&) = delete;
- Expr &operator=(const Expr&) = delete;
- Expr &operator=(Expr&&) = delete;
+ Expr &operator=(const Expr &) = delete;
+ Expr &operator=(Expr &&) = delete;
protected:
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK)
@@ -128,7 +128,7 @@ class Expr : public ValueStmt {
}
/// Construct an empty expression.
- explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { }
+ explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) {}
/// Each concrete expr subclass is expected to compute its dependence and call
/// this in the constructor.
@@ -153,6 +153,12 @@ class Expr : public ValueStmt {
TR = t;
}
+ /// If this expression is an enumeration constant, return the
+ /// enumeration type under which said constant was declared.
+ /// Otherwise return the expression's type.
+ /// Note this effectively circumvents the weak typing of C's enum constants
+ QualType getEnumCoercedType(const ASTContext &Ctx) const;
+
ExprDependence getDependence() const {
return static_cast<ExprDependence>(ExprBits.Dependent);
}
@@ -294,7 +300,7 @@ class Expr : public ValueStmt {
MLV_IncompleteVoidType,
MLV_DuplicateVectorComponents,
MLV_InvalidExpression,
- MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
+ MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
MLV_IncompleteType,
MLV_ConstQualified,
MLV_ConstQualifiedField,
@@ -327,25 +333,26 @@ class Expr : public ValueStmt {
enum Kinds {
CL_LValue,
CL_XValue,
- CL_Function, // Functions cannot be lvalues in C.
- CL_Void, // Void cannot be an lvalue in C.
+ CL_Function, // Functions cannot be lvalues in C.
+ CL_Void, // Void cannot be an lvalue in C.
CL_AddressableVoid, // Void expression whose address can be taken in C.
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
CL_MemberFunction, // An expression referring to a member function
CL_SubObjCPropertySetting,
- CL_ClassTemporary, // A temporary of class type, or subobject thereof.
- CL_ArrayTemporary, // A temporary of array type.
+ CL_ClassTemporary, // A temporary of class type, or subobject thereof.
+ CL_ArrayTemporary, // A temporary of array type.
CL_ObjCMessageRValue, // ObjC message is an rvalue
- CL_PRValue // A prvalue for any other reason, of any other type
+ CL_PRValue // A prvalue for any other reason, of any other type
};
/// The results of modification testing.
enum ModifiableType {
CM_Untested, // testModifiable was false.
CM_Modifiable,
- CM_RValue, // Not modifiable because it's an rvalue
- CM_Function, // Not modifiable because it's a function; C++ only
+ CM_RValue, // Not modifiable because it's an rvalue
+ CM_Function, // Not modifiable because it's a function; C++ only
CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
- CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
+ CM_NoSetterProperty, // Implicit assignment to ObjC property without
+ // setter
CM_ConstQualified,
CM_ConstQualifiedField,
CM_ConstAddrSpace,
@@ -360,8 +367,7 @@ class Expr : public ValueStmt {
unsigned short Modifiable;
explicit Classification(Kinds k, ModifiableType m)
- : Kind(k), Modifiable(m)
- {}
+ : Kind(k), Modifiable(m) {}
public:
Classification() {}
@@ -382,7 +388,6 @@ class Expr : public ValueStmt {
static Classification makeSimpleLValue() {
return Classification(CL_LValue, CM_Modifiable);
}
-
};
/// Classify - Classify this expression according to the C++11
/// expression taxonomy.
@@ -408,7 +413,8 @@ class Expr : public ValueStmt {
/// expression is modifiable (C99 6.3.2.1p1).
/// \param Loc A source location that might be filled with a relevant location
/// if the expression is not modifiable.
- Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{
+ Classification ClassifyModifiable(ASTContext &Ctx,
+ SourceLocation &Loc) const {
return ClassifyImpl(Ctx, &Loc);
}
@@ -421,9 +427,9 @@ class Expr : public ValueStmt {
static ExprValueKind getValueKindForType(QualType T) {
if (const ReferenceType *RT = T->getAs<ReferenceType>())
return (isa<LValueReferenceType>(RT)
- ? VK_LValue
- : (RT->getPointeeType()->isFunctionType()
- ? VK_LValue : VK_XValue));
+ ? VK_LValue
+ : (RT->getPointeeType()->isFunctionType() ? VK_LValue
+ : VK_XValue));
return VK_PRValue;
}
@@ -454,7 +460,6 @@ class Expr : public ValueStmt {
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
public:
-
/// Returns true if this expression is a gl-value that
/// potentially refers to a bit-field.
///
@@ -472,12 +477,19 @@ class Expr : public ValueStmt {
FieldDecl *getSourceBitField();
const FieldDecl *getSourceBitField() const {
- return const_cast<Expr*>(this)->getSourceBitField();
+ return const_cast<Expr *>(this)->getSourceBitField();
+ }
+
+ /// If this expression refers to an enum constant, retrieve its declaration
+ EnumConstantDecl *getEnumConstantDecl();
+
+ const EnumConstantDecl *getEnumConstantDecl() const {
+ return const_cast<Expr *>(this)->getEnumConstantDecl();
}
Decl *getReferencedDeclOfCallee();
const Decl *getReferencedDeclOfCallee() const {
- return const_cast<Expr*>(this)->getReferencedDeclOfCallee();
+ return const_cast<Expr *>(this)->getReferencedDeclOfCallee();
}
/// If this expression is an l-value for an Objective C
@@ -500,9 +512,7 @@ class Expr : public ValueStmt {
bool refersToGlobalRegisterVar() const;
/// Returns whether this expression has a placeholder type.
- bool hasPlaceholderType() const {
- return getType()->isPlaceholderType();
- }
+ bool hasPlaceholderType() const { return getType()->isPlaceholderType(); }
/// Returns whether this expression has a specific placeholder type.
bool hasPlaceholderType(BuiltinType::Kind K) const {
@@ -562,19 +572,18 @@ class Expr : public ValueStmt {
/// might be usable in a constant expression in C++11, if it were marked
/// constexpr. Return false if the function can never produce a constant
/// expression, along with diagnostics describing why not.
- static bool isPotentialConstantExpr(const FunctionDecl *FD,
- SmallVectorImpl<
- PartialDiagnosticAt> &Diags);
+ static bool
+ isPotentialConstantExpr(const FunctionDecl *FD,
+ SmallVectorImpl<PartialDiagnosticAt> &Diags);
/// isPotentialConstantExprUnevaluated - Return true if this expression might
/// be usable in a constant expression in C++11 in an unevaluated context, if
/// it were in function FD marked constexpr. Return false if the function can
/// never produce a constant expression, along with diagnostics describing
/// why not.
- static bool isPotentialConstantExprUnevaluated(Expr *E,
- const FunctionDecl *FD,
- SmallVectorImpl<
- PartialDiagnosticAt> &Diags);
+ static bool isPotentialConstantExprUnevaluated(
+ Expr *E, const FunctionDecl *FD,
+ SmallVectorImpl<PartialDiagnosticAt> &Diags);
/// isConstantInitializer - Returns true if this expression can be emitted to
/// IR as a constant, and thus can be used as a constant initializer in C.
@@ -620,9 +629,7 @@ class Expr : public ValueStmt {
// hasSideEffects - Return true if the evaluated expression has
// side effects.
- bool hasSideEffects() const {
- return HasSideEffects;
- }
+ bool hasSideEffects() const { return HasSideEffects; }
};
/// EvalResult is a struct with detailed info about an evaluated expression.
@@ -729,7 +736,7 @@ class Expr : public ValueStmt {
/// constant.
bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
const FunctionDecl *Callee,
- ArrayRef<const Expr*> Args,
+ ArrayRef<const Expr *> Args,
const Expr *This = nullptr) const;
enum class ConstantExprKind {
@@ -815,9 +822,9 @@ class Expr : public ValueStmt {
/// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
/// a Null pointer constant. The return value can further distinguish the
/// kind of NULL pointer constant that was detected.
- NullPointerConstantKind isNullPointerConstant(
- ASTContext &Ctx,
- NullPointerConstantValueDependence NPC) const;
+ NullPointerConstantKind
+ isNullPointerConstant(ASTContext &Ctx,
+ NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
@@ -1003,7 +1010,7 @@ class Expr : public ValueStmt {
/// Checks that the two Expr's will refer to the same value as a comparison
/// operand. The caller must ensure that the values referenced by the Expr's
/// are not modified between E1 and E2 or the result my be invalid.
- static bool isSameComparisonOperand(const Expr* E1, const Expr* E2);
+ static bool isSameComparisonOperand(const Expr *E1, const Expr *E2);
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
@@ -1025,16 +1032,16 @@ using ConstantExprKind = Expr::ConstantExprKind;
/// FullExpr - Represents a "full-expression" node.
class FullExpr : public Expr {
protected:
- Stmt *SubExpr;
-
- FullExpr(StmtClass SC, Expr *subexpr)
- : Expr(SC, subexpr->getType(), subexpr->getValueKind(),
- subexpr->getObjectKind()),
- SubExpr(subexpr) {
- setDependence(computeDependence(this));
- }
- FullExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty) {}
+ Stmt *SubExpr;
+
+ FullExpr(StmtClass SC, Expr *subexpr)
+ : Expr(SC, subexpr->getType(), subexpr->getValueKind(),
+ subexpr->getObjectKind()),
+ SubExpr(subexpr) {
+ setDependence(computeDependence(this));
+ }
+ FullExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {}
+
public:
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
@@ -1137,7 +1144,7 @@ class ConstantExpr final
APValue getAPValueResult() const;
llvm::APSInt getResultAsAPSInt() const;
// Iterators
- child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
const_child_range children() const {
return const_child_range(&SubExpr, &SubExpr + 1);
}
@@ -1171,7 +1178,7 @@ class OpaqueValueExpr : public Expr {
static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
explicit OpaqueValueExpr(EmptyShell Empty)
- : Expr(OpaqueValueExprClass, Empty) {}
+ : Expr(OpaqueValueExprClass, Empty) {}
/// Retrieve the location of this expression.
SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; }
@@ -1483,7 +1490,7 @@ class IntegerLiteral : public Expr, public APIntStorage {
/// Construct an empty integer literal.
explicit IntegerLiteral(EmptyShell Empty)
- : Expr(IntegerLiteralClass, Empty) { }
+ : Expr(IntegerLiteralClass, Empty) {}
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
@@ -1529,7 +1536,7 @@ class FixedPointLiteral : public Expr, public APIntStorage {
explicit FixedPointLiteral(EmptyShell Empty)
: Expr(FixedPointLiteralClass, Empty) {}
- public:
+public:
FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
SourceLocation l, unsigned Scale);
@@ -1573,6 +1580,7 @@ enum class CharacterLiteralKind { Ascii, Wide, UTF8, UTF16, UTF32 };
class CharacterLiteral : public Expr {
unsigned Value;
SourceLocation Loc;
+
public:
// type should be IntTy
CharacterLiteral(unsigned value, CharacterLiteralKind kind, QualType type,
@@ -1584,7 +1592,7 @@ class CharacterLiteral : public Expr {
}
/// Construct an empty character literal.
- CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+ CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) {}
SourceLocation getLocation() const { return Loc; }
CharacterLiteralKind getKind() const {
@@ -1698,6 +1706,7 @@ class FloatingLiteral : public Expr, private APFloatStorage {
///
class ImaginaryLiteral : public Expr {
Stmt *Val;
+
public:
ImaginaryLiteral(Expr *val, QualType Ty)
: Expr(ImaginaryLiteralClass, Ty, VK_PRValue, OK_Ordinary), Val(val) {
@@ -1706,7 +1715,7 @@ class ImaginaryLiteral : public Expr {
/// Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
- : Expr(ImaginaryLiteralClass, Empty) { }
+ : Expr(ImaginaryLiteralClass, Empty) {}
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
@@ -1722,7 +1731,7 @@ class ImaginaryLiteral : public Expr {
}
// Iterators
- child_range children() { return child_range(&Val, &Val+1); }
+ child_range children() { return child_range(&Val, &Val + 1); }
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}
@@ -1875,7 +1884,9 @@ class StringLiteral final
bool isUTF8() const { return getKind() == StringLiteralKind::UTF8; }
bool isUTF16() const { return getKind() == StringLiteralKind::UTF16; }
bool isUTF32() const { return getKind() == StringLiteralKind::UTF32; }
- bool isUnevaluated() const { return getKind() == StringLiteralKind::Unevaluated; }
+ bool isUnevaluated() const {
+ return getKind() == StringLiteralKind::Unevaluated;
+ }
bool isPascal() const { return StringLiteralBits.IsPascal; }
bool containsNonAscii() const {
@@ -2105,6 +2116,7 @@ class SYCLUniqueStableNameExpr final : public Expr {
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;
+
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(), val->getValueKind(),
@@ -2114,8 +2126,7 @@ class ParenExpr : public Expr {
}
/// Construct an empty parenthesized expression.
- explicit ParenExpr(EmptyShell Empty)
- : Expr(ParenExprClass, Empty) { }
+ explicit ParenExpr(EmptyShell Empty) : Expr(ParenExprClass, Empty) {}
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
@@ -2137,7 +2148,7 @@ class ParenExpr : public Expr {
}
// Iterators
- child_range children() { return child_range(&Val, &Val+1); }
+ child_range children() { return child_range(&Val, &Val + 1); }
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}
@@ -2234,9 +2245,7 @@ class UnaryOperator final
}
/// isPrefix - Return true if this is a prefix operation, like --x.
- static bool isPrefix(Opcode Op) {
- return Op == UO_PreInc || Op == UO_PreDec;
- }
+ static bool isPrefix(Opcode Op) { return Op == UO_PreInc || Op == UO_PreDec; }
bool isPrefix() const { return isPrefix(getOpcode()); }
bool isPostfix() const { return isPostfix(getOpcode()); }
@@ -2244,16 +2253,12 @@ class UnaryOperator final
static bool isIncrementOp(Opcode Op) {
return Op == UO_PreInc || Op == UO_PostInc;
}
- bool isIncrementOp() const {
- return isIncrementOp(getOpcode());
- }
+ bool isIncrementOp() const { return isIncrementOp(getOpcode()); }
static bool isDecrementOp(Opcode Op) {
return Op == UO_PreDec || Op == UO_PostDec;
}
- bool isDecrementOp() const {
- return isDecrementOp(getOpcode());
- }
+ bool isDecrementOp() const { return isDecrementOp(getOpcode()); }
static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
bool isIncrementDecrementOp() const {
@@ -2290,7 +2295,7 @@ class UnaryOperator final
}
// Iterators
- child_range children() { return child_range(&Val, &Val+1); }
+ child_range children() { return child_range(&Val, &Val + 1); }
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}
@@ -2450,24 +2455,22 @@ class OffsetOfExpr final
return NumComps;
}
- OffsetOfExpr(const ASTContext &C, QualType type,
- SourceLocation OperatorLoc, TypeSourceInfo *tsi,
- ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
- SourceLocation RParenLoc);
+ OffsetOfExpr(const ASTContext &C, QualType type, SourceLocation OperatorLoc,
+ TypeSourceInfo *tsi, ArrayRef<OffsetOfNode> comps,
+ ArrayRef<Expr *> exprs, SourceLocation RParenLoc);
explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
- : Expr(OffsetOfExprClass, EmptyShell()),
- TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}
+ : Expr(OffsetOfExprClass, EmptyShell()), TSInfo(nullptr),
+ NumComps(numComps), NumExprs(numExprs) {}
public:
-
static OffsetOfExpr *Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
- ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/81389
More information about the cfe-commits
mailing list