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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits