diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 188 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 449 |
2 files changed, 383 insertions, 254 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 6cda82b2b0c..d3157680222 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1,4 +1,4 @@ -//===--- Expr.cpp - Expression AST Node Implementation --------------------===// +//===- Expr.cpp - Expression AST Node Implementation ----------------------===// // // The LLVM Compiler Infrastructure // @@ -11,28 +11,62 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtVisitor.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/LiteralSupport.h" -#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <cstring> +#include <memory> +#include <string> +#include <utility> + using namespace clang; const Expr *Expr::getBestDynamicClassTypeExpr() const { @@ -193,24 +227,23 @@ bool Expr::isKnownToHaveBooleanValue() const { // a more specific implementation of getExprLoc(). // // See also Stmt.cpp:{getLocStart(),getLocEnd()}. -namespace { - /// This implementation is used when a class provides a custom - /// implementation of getExprLoc. - template <class E, class T> - SourceLocation getExprLocImpl(const Expr *expr, - SourceLocation (T::*v)() const) { - return static_cast<const E*>(expr)->getExprLoc(); - } - /// This implementation is used when a class doesn't provide - /// a custom implementation of getExprLoc. Overload resolution - /// should pick it over the implementation above because it's - /// more specialized according to function template partial ordering. - template <class E> - SourceLocation getExprLocImpl(const Expr *expr, - SourceLocation (Expr::*v)() const) { - return static_cast<const E*>(expr)->getLocStart(); - } +/// This implementation is used when a class provides a custom +/// implementation of getExprLoc. +template <class E, class T> +static SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (T::*v)() const) { + return static_cast<const E*>(expr)->getExprLoc(); +} + +/// This implementation is used when a class doesn't provide +/// a custom implementation of getExprLoc. Overload resolution +/// should pick it over the implementation above because it's +/// more specialized according to function template partial ordering. +template <class E> +static SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (Expr::*v)() const) { + return static_cast<const E*>(expr)->getLocStart(); } SourceLocation Expr::getExprLoc() const { @@ -452,6 +485,7 @@ SourceLocation DeclRefExpr::getLocStart() const { return getQualifierLoc().getBeginLoc(); return getNameInfo().getLocStart(); } + SourceLocation DeclRefExpr::getLocEnd() const { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -606,8 +640,9 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { POut << " &&"; } - typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy; + using SpecsTy = SmallVector<const ClassTemplateSpecializationDecl *, 8>; SpecsTy Specs; + const DeclContext *Ctx = FD->getDeclContext(); while (Ctx && isa<NamedDecl>(Ctx)) { const ClassTemplateSpecializationDecl *Spec @@ -765,7 +800,7 @@ FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, } FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty) { + : Expr(FloatingLiteralClass, Empty) { setRawSemantics(IEEEhalf); FloatingLiteralBits.IsExact = false; } @@ -1035,7 +1070,6 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str, /// Using these two parameters can reduce the time complexity from O(n^2) to /// O(n) if one wants to get the location of byte for all the tokens in a /// string. -/// SourceLocation StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, @@ -1054,7 +1088,7 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, StringOffset = *StartTokenByteOffset; ByteNo -= StringOffset; } - while (1) { + while (true) { assert(TokNo < getNumConcatenated() && "Invalid byte number!"); SourceLocation StrTokLoc = getStrTokenLoc(TokNo); @@ -1109,8 +1143,6 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, } } - - /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++". StringRef UnaryOperator::getOpcodeStr(Opcode Op) { @@ -1152,7 +1184,6 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { } } - //===----------------------------------------------------------------------===// // Postfix Operators. //===----------------------------------------------------------------------===// @@ -1164,7 +1195,6 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, fn->isValueDependent(), fn->isInstantiationDependent(), fn->containsUnexpandedParameterPack()), NumArgs(args.size()) { - unsigned NumPreArgs = preargs.size(); SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs]; SubExprs[FN] = fn; @@ -1188,15 +1218,15 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) { -} + : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, + rparenloc) {} CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {} CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { + : Expr(SC, Empty) { // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs](); CallExprBits.NumPreArgs = NumPreArgs; @@ -1332,6 +1362,7 @@ SourceLocation CallExpr::getLocStart() const { begin = getArg(0)->getLocStart(); return begin; } + SourceLocation CallExpr::getLocEnd() const { if (isa<CXXOperatorCallExpr>(this)) return cast<CXXOperatorCallExpr>(this)->getLocEnd(); @@ -1393,7 +1424,7 @@ IdentifierInfo *OffsetOfNode::getFieldName() const { if (getKind() == Field) return getField()->getIdentifier(); - return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask); + return reinterpret_cast<IdentifierInfo *>(Data & ~(uintptr_t)Mask); } UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( @@ -1440,7 +1471,6 @@ MemberExpr *MemberExpr::Create( ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, QualType ty, ExprValueKind vk, ExprObjectKind ok) { - bool hasQualOrFound = (QualifierLoc || founddecl.getDecl() != memberdecl || founddecl.getAccess() != memberdecl->getAccess()); @@ -1508,6 +1538,7 @@ SourceLocation MemberExpr::getLocStart() const { return BaseStartLoc; return MemberLoc; } + SourceLocation MemberExpr::getLocEnd() const { SourceLocation EndLoc = getMemberNameInfo().getEndLoc(); if (hasExplicitTemplateArgs()) @@ -1641,19 +1672,17 @@ const char *CastExpr::getCastKindName() const { llvm_unreachable("Unhandled cast kind!"); } -namespace { - Expr *skipImplicitTemporary(Expr *expr) { - // Skip through reference binding to temporary. - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(expr)) - expr = Materialize->GetTemporaryExpr(); +static Expr *skipImplicitTemporary(Expr *expr) { + // Skip through reference binding to temporary. + if (MaterializeTemporaryExpr *Materialize + = dyn_cast<MaterializeTemporaryExpr>(expr)) + expr = Materialize->GetTemporaryExpr(); - // Skip any temporary bindings; they're implicit. - if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr)) - expr = Binder->getSubExpr(); + // Skip any temporary bindings; they're implicit. + if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr)) + expr = Binder->getSubExpr(); - return expr; - } + return expr; } Expr *CastExpr::getSubExprAsWritten() { @@ -1861,13 +1890,13 @@ bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx, return true; } + InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, ArrayRef<Expr*> initExprs, SourceLocation rbraceloc) - : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, - false, false), - InitExprs(C, initExprs.size()), - LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true) -{ + : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false, false), + InitExprs(C, initExprs.size()), + LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true) { sawArrayRangeDesignator(false); for (unsigned I = 0; I != initExprs.size(); ++I) { if (initExprs[I]->isTypeDependent()) @@ -1999,7 +2028,6 @@ SourceLocation InitListExpr::getLocEnd() const { } /// getFunctionType - Return the underlying function type for this block. -/// const FunctionProtoType *BlockExpr::getFunctionType() const { // The block pointer is never sugared, but the function type might be. return cast<BlockPointerType>(getType()) @@ -2009,14 +2037,15 @@ const FunctionProtoType *BlockExpr::getFunctionType() const { SourceLocation BlockExpr::getCaretLocation() const { return TheBlock->getCaretLocation(); } + const Stmt *BlockExpr::getBody() const { return TheBlock->getBody(); } + Stmt *BlockExpr::getBody() { return TheBlock->getBody(); } - //===----------------------------------------------------------------------===// // Generic Expression Routines //===----------------------------------------------------------------------===// @@ -2211,7 +2240,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return false; case CXXTemporaryObjectExprClass: - case CXXConstructExprClass: { + case CXXConstructExprClass: if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) { if (Type->hasAttr<WarnUnusedAttr>()) { WarnE = this; @@ -2221,7 +2250,6 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } } return false; - } case ObjCMessageExprClass: { const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this); @@ -2894,7 +2922,6 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, case MaterializeTemporaryExprClass: return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false, Culprit); - case SubstNonTypeTemplateParmExprClass: return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement() ->isConstantInitializer(Ctx, false, Culprit); @@ -2916,16 +2943,17 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, } namespace { + /// \brief Look for any side effects within a Stmt. class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> { - typedef ConstEvaluatedExprVisitor<SideEffectFinder> Inherited; + using Inherited = ConstEvaluatedExprVisitor<SideEffectFinder>; + const bool IncludePossibleEffects; - bool HasSideEffects; + bool HasSideEffects = false; public: explicit SideEffectFinder(const ASTContext &Context, bool IncludePossible) - : Inherited(Context), - IncludePossibleEffects(IncludePossible), HasSideEffects(false) { } + : Inherited(Context), IncludePossibleEffects(IncludePossible) {} bool hasSideEffects() const { return HasSideEffects; } @@ -2935,7 +2963,8 @@ namespace { HasSideEffects = true; } }; -} + +} // namespace bool Expr::HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects) const { @@ -3211,16 +3240,17 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, } namespace { + /// \brief Look for a call to a non-trivial function within an expression. - class NonTrivialCallFinder : public ConstEvaluatedExprVisitor<NonTrivialCallFinder> - { - typedef ConstEvaluatedExprVisitor<NonTrivialCallFinder> Inherited; + class NonTrivialCallFinder + : public ConstEvaluatedExprVisitor<NonTrivialCallFinder> { + using Inherited = ConstEvaluatedExprVisitor<NonTrivialCallFinder>; - bool NonTrivial; + bool NonTrivial = false; public: explicit NonTrivialCallFinder(const ASTContext &Context) - : Inherited(Context), NonTrivial(false) { } + : Inherited(Context) {} bool hasNonTrivialCall() const { return NonTrivial; } @@ -3256,7 +3286,8 @@ namespace { NonTrivial = true; } }; -} + +} // namespace bool Expr::hasNonTrivialCall(const ASTContext &Ctx) const { NonTrivialCallFinder Finder(Ctx); @@ -3282,7 +3313,6 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return NPCK_ZeroExpression; else return NPCK_NotNull; - case NPC_ValueDependentIsNotNull: return NPCK_NotNull; } @@ -3580,12 +3610,11 @@ void ExtVectorElementExpr::getEncodedElementAccess( ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type, SourceLocation BLoc, SourceLocation RP) - : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, - Type->isDependentType(), Type->isDependentType(), - Type->isInstantiationDependentType(), - Type->containsUnexpandedParameterPack()), - BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) -{ + : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, + Type->isDependentType(), Type->isDependentType(), + Type->isInstantiationDependentType(), + Type->containsUnexpandedParameterPack()), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) { SubExprs = new (C) Stmt*[args.size()]; for (unsigned i = 0; i != args.size(); i++) { if (args[i]->isTypeDependent()) @@ -3906,7 +3935,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, ArrayRef<Expr*> semantics, unsigned resultIndex) { assert(syntax && "no syntactic expression!"); - assert(semantics.size() && "no semantic expressions!"); + assert(!semantics.empty() && "no semantic expressions!"); QualType type; ExprValueKind VK; @@ -3980,10 +4009,9 @@ Stmt::const_child_range UnaryExprOrTypeTraitExpr::children() const { AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, AtomicOp op, SourceLocation RP) - : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, - false, false, false, false), - NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) -{ + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + false, false, false, false), + NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions"); for (unsigned i = 0; i != args.size(); i++) { if (args[i]->isTypeDependent()) @@ -4086,7 +4114,7 @@ QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) { if (OriginalTy->isAnyPointerType()) OriginalTy = OriginalTy->getPointeeType(); else { - assert (OriginalTy->isArrayType()); + assert(OriginalTy->isArrayType()); OriginalTy = OriginalTy->castAsArrayTypeUnsafe()->getElementType(); } } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ca07f7429e8..6b209cdef7c 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1,4 +1,4 @@ -//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===// +//===- SemaChecking.cpp - Extra Semantic Checking -------------------------===// // // The LLVM Compiler Infrastructure // @@ -12,35 +12,88 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/AttrIterator.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" +#include "clang/AST/NSAPI.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/UnresolvedSet.h" #include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OpenCLOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/SyncScope.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/Locale.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <functional> +#include <limits> +#include <string> +#include <tuple> +#include <utility> using namespace clang; using namespace sema; @@ -638,7 +691,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { // OpenCL v2.0 s6.13.16.2 - The built-in read/write // functions have two forms. switch (Call->getNumArgs()) { - case 2: { + case 2: if (checkOpenCLPipeArg(S, Call)) return true; // The call with 2 arguments should be @@ -646,7 +699,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { // Check packet type T. if (checkOpenCLPipePacketType(S, Call, 1)) return true; - } break; + break; case 4: { if (checkOpenCLPipeArg(S, Call)) @@ -753,6 +806,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { return false; } + // \brief OpenCL v2.0 s6.13.9 - Address space qualifier functions. // \brief Performs semantic analysis for the to_global/local/private call. // \param S Reference to the semantic analyzer. @@ -905,7 +959,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (checkArgCount(*this, TheCall, 1)) return true; break; - case Builtin::BI__builtin_classify_type: if (checkArgCount(*this, TheCall, 1)) return true; TheCall->setType(Context.IntTy); @@ -1170,9 +1223,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, break; case Builtin::BI__builtin_os_log_format: case Builtin::BI__builtin_os_log_format_buffer_size: - if (SemaBuiltinOSLogFormat(TheCall)) { + if (SemaBuiltinOSLogFormat(TheCall)) return ExprError(); - } break; } @@ -2508,6 +2560,7 @@ bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { } return false; } + /// \brief Diagnose use of %s directive in an NSString which is being passed /// as formatting string to formatting method. static void @@ -2874,23 +2927,32 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, enum { // C __c11_atomic_init(A *, C) Init, + // C __c11_atomic_load(A *, int) Load, + // void __atomic_load(A *, CP, int) LoadCopy, + // void __atomic_store(A *, CP, int) Copy, + // C __c11_atomic_add(A *, M, int) Arithmetic, + // C __atomic_exchange_n(A *, CP, int) Xchg, + // void __atomic_exchange(A *, C *, CP, int) GNUXchg, + // bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int) C11CmpXchg, + // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int) GNUCmpXchg } Form = Init; + const unsigned NumForm = GNUCmpXchg + 1; const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 3, 4, 5, 6 }; const unsigned NumVals[] = { 1, 0, 1, 1, 1, 1, 2, 2, 3 }; @@ -3783,7 +3845,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) { bool IsWindows = TT.isOSWindows(); bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start; if (IsX64 || IsAArch64) { - clang::CallingConv CC = CC_C; + CallingConv CC = CC_C; if (const FunctionDecl *FD = S.getCurFunctionDecl()) CC = FD->getType()->getAs<FunctionType>()->getCallConv(); if (IsMSVAStart) { @@ -4305,9 +4367,9 @@ bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) { << (unsigned)Context.getCharWidth() << Arg->getSourceRange(); - if (Result > INT32_MAX) + if (Result > std::numeric_limits<int32_t>::max()) return Diag(TheCall->getLocStart(), diag::err_alignment_too_big) - << INT32_MAX + << std::numeric_limits<int32_t>::max() << Arg->getSourceRange(); } @@ -4572,7 +4634,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, if (!ValidString) return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg) << Arg->getSourceRange(); - } else if (IsAArch64Builtin && Fields.size() == 1) { // If the register name is one of those that appear in the condition below // and the special register builtin being used is one of the write builtins, @@ -4626,13 +4687,15 @@ bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) { } namespace { + class UncoveredArgHandler { enum { Unknown = -1, AllCovered = -2 }; - signed FirstUncoveredArg; + + signed FirstUncoveredArg = Unknown; SmallVector<const Expr *, 4> DiagnosticExprs; public: - UncoveredArgHandler() : FirstUncoveredArg(Unknown) { } + UncoveredArgHandler() = default; bool hasUncoveredArg() const { return (FirstUncoveredArg >= 0); @@ -4676,7 +4739,8 @@ enum StringLiteralCheckType { SLCT_UncheckedLiteral, SLCT_CheckedLiteral }; -} // end anonymous namespace + +} // namespace static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend, BinaryOperatorKind BinOpKind, @@ -4709,7 +4773,8 @@ static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend, // We add an offset to a pointer here so we should support an offset as big as // possible. if (Ov) { - assert(BitWidth <= UINT_MAX / 2 && "index (intermediate) result too big"); + assert(BitWidth <= std::numeric_limits<unsigned>::max() / 2 && + "index (intermediate) result too big"); Offset = Offset.sext(2 * BitWidth); sumOffsets(Offset, Addend, BinOpKind, AddendIsRight); return; @@ -4719,6 +4784,7 @@ static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend, } namespace { + // This is a wrapper class around StringLiteral to support offsetted string // literals as format strings. It takes the offset into account when returning // the string and its length or the source locations to display notes correctly. @@ -4737,6 +4803,7 @@ class FormatStringLiteral { unsigned getByteLength() const { return FExpr->getByteLength() - getCharByteWidth() * Offset; } + unsigned getLength() const { return FExpr->getLength() - Offset; } unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); } @@ -4762,9 +4829,11 @@ class FormatStringLiteral { SourceLocation getLocStart() const LLVM_READONLY { return FExpr->getLocStart().getLocWithOffset(Offset); } + SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); } }; -} // end anonymous namespace + +} // namespace static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr, @@ -4851,10 +4920,9 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return (CheckLeft && Left < Right) ? Left : Right; } - case Stmt::ImplicitCastExprClass: { + case Stmt::ImplicitCastExprClass: E = cast<ImplicitCastExpr>(E)->getSubExpr(); goto tryAgain; - } case Stmt::OpaqueValueExprClass: if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) { @@ -5043,7 +5111,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, case Stmt::UnaryOperatorClass: { const UnaryOperator *UnaOp = cast<UnaryOperator>(E); auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); - if (UnaOp->getOpcode() == clang::UO_AddrOf && ASE) { + if (UnaOp->getOpcode() == UO_AddrOf && ASE) { llvm::APSInt IndexResult; if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true); @@ -5176,6 +5244,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, } namespace { + class CheckFormatHandler : public analyze_format_string::FormatStringHandler { protected: Sema &S; @@ -5189,8 +5258,8 @@ protected: ArrayRef<const Expr *> Args; unsigned FormatIdx; llvm::SmallBitVector CoveredArgs; - bool usesPositionalArgs; - bool atFirstArg; + bool usesPositionalArgs = false; + bool atFirstArg = true; bool inFunctionCall; Sema::VariadicCallType CallType; llvm::SmallBitVector &CheckedVarArgs; @@ -5208,7 +5277,6 @@ public: : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type), FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg), HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx), - usesPositionalArgs(false), atFirstArg(true), inFunctionCall(inFunctionCall), CallType(callType), CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) { CoveredArgs.resize(numDataArgs); @@ -5278,7 +5346,8 @@ protected: bool IsStringLocation, Range StringRange, ArrayRef<FixItHint> Fixit = None); }; -} // end anonymous namespace + +} // namespace SourceRange CheckFormatHandler::getFormatStringRange() { return OrigFormatExpr->getSourceRange(); @@ -5632,6 +5701,7 @@ void CheckFormatHandler::EmitFormatDiagnostic( //===--- CHECK: Printf format string checking ------------------------------===// namespace { + class CheckPrintfHandler : public CheckFormatHandler { public: CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr, @@ -5696,7 +5766,8 @@ public: const char *conversionPosition) override; }; -} // end anonymous namespace + +} // namespace bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( const analyze_printf::PrintfSpecifier &FS, @@ -5814,10 +5885,6 @@ void CheckPrintfHandler::HandleIgnoredFlag( getSpecifierRange(ignoredFlag.getPosition(), 1))); } -// void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, -// bool IsStringLocation, Range StringRange, -// ArrayRef<FixItHint> Fixit = None); - void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag, unsigned flagLen) { // Warn about an empty flag. @@ -5884,7 +5951,8 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { /// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't /// allow the call, or if it would be ambiguous). bool Sema::hasCStrMethod(const Expr *E) { - typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet; + using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>; + MethodSet Results = CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType()); for (MethodSet::iterator MI = Results.begin(), ME = Results.end(); @@ -5899,7 +5967,7 @@ bool Sema::hasCStrMethod(const Expr *E) { // Returns true when a c_str() conversion method is found. bool CheckPrintfHandler::checkForCStrMembers( const analyze_printf::ArgType &AT, const Expr *E) { - typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet; + using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>; MethodSet Results = CXXRecordMembersNamed<CXXMethodDecl>("c_str", S, E->getType()); @@ -5927,7 +5995,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier const char *startSpecifier, unsigned specifierLen) { using namespace analyze_format_string; - using namespace analyze_printf; + using namespace analyze_printf; + const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); if (FS.consumesDataArgument()) { @@ -6225,6 +6294,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, const Expr *E) { using namespace analyze_format_string; using namespace analyze_printf; + // Now type check the data expression that matches the // format specifier. const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext()); @@ -6477,6 +6547,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, //===--- CHECK: Scanf format string checking ------------------------------===// namespace { + class CheckScanfHandler : public CheckFormatHandler { public: CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr, @@ -6503,7 +6574,8 @@ public: void HandleIncompleteScanList(const char *start, const char *end) override; }; -} // end anonymous namespace + +} // namespace void CheckScanfHandler::HandleIncompleteScanList(const char *start, const char *end) { @@ -6516,7 +6588,6 @@ bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier( const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) { - const analyze_scanf::ScanfConversionSpecifier &CS = FS.getConversionSpecifier(); @@ -7258,7 +7329,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, static const Expr *getSizeOfExprArg(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) - if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) + if (SizeOf->getKind() == UETT_SizeOf && !SizeOf->isArgumentType()) return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); return nullptr; @@ -7268,7 +7339,7 @@ static const Expr *getSizeOfExprArg(const Expr *E) { static QualType getSizeOfArgType(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) - if (SizeOf->getKind() == clang::UETT_SizeOf) + if (SizeOf->getKind() == UETT_SizeOf) return SizeOf->getTypeOfArgument(); return QualType(); @@ -7456,7 +7527,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) { Ex = Ex->IgnoreParenCasts(); - for (;;) { + while (true) { const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex); if (!BO || !BO->isAdditiveOp()) break; @@ -7674,7 +7745,6 @@ static const Expr *EvalAddr(const Expr *E, static void CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc) { - const Expr *stackE = nullptr; SmallVector<const DeclRefExpr *, 8> refVars; @@ -8159,8 +8229,7 @@ struct IntRange { bool NonNegative; IntRange(unsigned Width, bool NonNegative) - : Width(Width), NonNegative(NonNegative) - {} + : Width(Width), NonNegative(NonNegative) {} /// Returns the range of the bool type. static IntRange forBoolType() { @@ -8249,7 +8318,10 @@ struct IntRange { } }; -IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { +} // namespace + +static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, + unsigned MaxWidth) { if (value.isSigned() && value.isNegative()) return IntRange(value.getMinSignedBits(), false); @@ -8261,8 +8333,8 @@ IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { return IntRange(value.getActiveBits(), true); } -IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, - unsigned MaxWidth) { +static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, + unsigned MaxWidth) { if (result.isInt()) return GetValueRange(C, result.getInt(), MaxWidth); @@ -8290,7 +8362,7 @@ IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); } -QualType GetExprType(const Expr *E) { +static QualType GetExprType(const Expr *E) { QualType Ty = E->getType(); if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>()) Ty = AtomicRHS->getValueType(); @@ -8301,7 +8373,7 @@ QualType GetExprType(const Expr *E) { /// range of values it might take. /// /// \param MaxWidth - the width to which the value will be truncated -IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { +static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { E = E->IgnoreParens(); // Try a full evaluation first. @@ -8519,16 +8591,16 @@ IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { return IntRange::forValueOfType(C, GetExprType(E)); } -IntRange GetExprRange(ASTContext &C, const Expr *E) { +static IntRange GetExprRange(ASTContext &C, const Expr *E) { return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); } /// Checks whether the given value, which currently has the given /// source semantics, has the same value when coerced through the /// target semantics. -bool IsSameFloatAfterCast(const llvm::APFloat &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { llvm::APFloat truncated = value; bool ignored; @@ -8543,9 +8615,9 @@ bool IsSameFloatAfterCast(const llvm::APFloat &value, /// target semantics. /// /// The value might be a vector of floats (or a complex number). -bool IsSameFloatAfterCast(const APValue &value, - const llvm::fltSemantics &Src, - const llvm::fltSemantics &Tgt) { +static bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { if (value.isFloat()) return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); @@ -8561,9 +8633,9 @@ bool IsSameFloatAfterCast(const APValue &value, IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); } -void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); +static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); -bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { +static bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { // Suppress cases where we are comparing against an enum constant. if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) @@ -8577,11 +8649,11 @@ bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { return false; } -bool isNonBooleanIntegerValue(Expr *E) { +static bool isNonBooleanIntegerValue(Expr *E) { return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType(); } -bool isNonBooleanUnsignedValue(Expr *E) { +static bool isNonBooleanUnsignedValue(Expr *E) { // We are checking that the expression is not known to have boolean value, // is an integer type; and is either unsigned after implicit casts, // or was unsigned before implicit casts. @@ -8590,6 +8662,8 @@ bool isNonBooleanUnsignedValue(Expr *E) { !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType()); } +namespace { + enum class LimitType { Max = 1U << 0U, // e.g. 32767 for short Min = 1U << 1U, // e.g. -32768 for short @@ -8597,12 +8671,15 @@ enum class LimitType { // same time; e.g. in C++, A::a in enum A { a = 0 }; }; +} // namespace + /// Checks whether Expr 'Constant' may be the /// std::numeric_limits<>::max() or std::numeric_limits<>::min() /// of the Expr 'Other'. If true, then returns the limit type (min or max). /// The Value is the evaluation of Constant -llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant, Expr *Other, - const llvm::APSInt &Value) { +static llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant, + Expr *Other, + const llvm::APSInt &Value) { if (IsEnumConstOrFromMacro(S, Constant)) return llvm::Optional<LimitType>(); @@ -8636,7 +8713,7 @@ llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant, Expr *Other, return llvm::None; } -bool HasEnumType(Expr *E) { +static bool HasEnumType(Expr *E) { // Strip off implicit integral promotions. while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { if (ICE->getCastKind() != CK_IntegralCast && @@ -8648,9 +8725,10 @@ bool HasEnumType(Expr *E) { return E->getType()->isEnumeralType(); } -bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, Expr *Constant, - Expr *Other, const llvm::APSInt &Value, - bool RhsConstant) { +static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, + Expr *Constant, Expr *Other, + const llvm::APSInt &Value, + bool RhsConstant) { // Disable warning in template instantiations // and only analyze <, >, <= and >= operations. if (S.inTemplateInstantiation() || !E->isRelationalOp()) @@ -8696,9 +8774,10 @@ bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, Expr *Constant, return true; } -bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, - Expr *Other, const llvm::APSInt &Value, - bool RhsConstant) { +static bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, + Expr *Constant, Expr *Other, + const llvm::APSInt &Value, + bool RhsConstant) { // Disable warning in template instantiations. if (S.inTemplateInstantiation()) return false; @@ -8907,7 +8986,7 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, /// Analyze the operands of the given comparison. Implements the /// fallback case from AnalyzeComparison. -void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); } @@ -8915,7 +8994,7 @@ void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { /// \brief Implements -Wsign-compare. /// /// \param E the binary operator to check for warnings -void AnalyzeComparison(Sema &S, BinaryOperator *E) { +static void AnalyzeComparison(Sema &S, BinaryOperator *E) { // The type the comparison is being performed in. QualType T = E->getLHS()->getType(); @@ -9023,8 +9102,8 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { /// Analyzes an attempt to assign the given value to a bitfield. /// /// Returns true if there was something fishy about the attempt. -bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, - SourceLocation InitLoc) { +static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, + SourceLocation InitLoc) { assert(Bitfield->isBitField()); if (Bitfield->isInvalidDecl()) return false; @@ -9154,7 +9233,7 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, /// Analyze the given simple or compound assignment for warning-worthy /// operations. -void AnalyzeAssignment(Sema &S, BinaryOperator *E) { +static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { // Just recurse on the LHS. AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); @@ -9173,9 +9252,9 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) { } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, - SourceLocation CContext, unsigned diag, - bool pruneControlFlow = false) { +static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { if (pruneControlFlow) { S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag) @@ -9188,16 +9267,16 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, - unsigned diag, bool pruneControlFlow = false) { +static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, + SourceLocation CContext, + unsigned diag, bool pruneControlFlow = false) { DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } /// Diagnose an implicit cast from a floating point value to an integer value. -void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, - - SourceLocation CContext) { +static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, + SourceLocation CContext) { const bool IsBool = T->isSpecificBuiltinType(BuiltinType::Bool); const bool PruneWarnings = S.inTemplateInstantiation(); @@ -9287,7 +9366,8 @@ void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, } } -std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { +static std::string PrettyPrintInRange(const llvm::APSInt &Value, + IntRange Range) { if (!Range.Width) return "0"; llvm::APSInt ValueInRange = Value; @@ -9296,7 +9376,7 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } -bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { +static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { if (!isa<ImplicitCastExpr>(Ex)) return false; @@ -9315,8 +9395,8 @@ bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { FloatCandidateBT && (FloatCandidateBT->isFloatingPoint())); } -void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, - SourceLocation CC) { +static void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, + SourceLocation CC) { unsigned NumArgs = TheCall->getNumArgs(); for (unsigned i = 0; i < NumArgs; ++i) { Expr *CurrA = TheCall->getArg(i); @@ -9336,7 +9416,8 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, } } -void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) { +static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC) { if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer, E->getExprLoc())) return; @@ -9380,20 +9461,24 @@ void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, SourceLocation CC) { return; S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) - << (NullKind == Expr::NPCK_CXX11_nullptr) << T << clang::SourceRange(CC) + << (NullKind == Expr::NPCK_CXX11_nullptr) << T << SourceRange(CC) << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T, Loc)); } -void checkObjCArrayLiteral(Sema &S, QualType TargetType, - ObjCArrayLiteral *ArrayLiteral); -void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, - ObjCDictionaryLiteral *DictionaryLiteral); +static void checkObjCArrayLiteral(Sema &S, QualType TargetType, + ObjCArrayLiteral *ArrayLiteral); + +static void +checkObjCDictionaryLiteral(Sema &S, QualType TargetType, + ObjCDictionaryLiteral *DictionaryLiteral); /// Check a single element within a collection literal against the /// target element type. -void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType, - Expr *Element, unsigned ElementKind) { +static void checkObjCCollectionLiteralElement(Sema &S, + QualType TargetElementType, + Expr *Element, + unsigned ElementKind) { // Skip a bitcast to 'id' or qualified 'id'. if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) { if (ICE->getCastKind() == CK_BitCast && @@ -9422,8 +9507,8 @@ void checkObjCCollectionLiteralElement(Sema &S, QualType TargetElementType, /// Check an Objective-C array literal being converted to the given /// target type. -void checkObjCArrayLiteral(Sema &S, QualType TargetType, - ObjCArrayLiteral *ArrayLiteral) { +static void checkObjCArrayLiteral(Sema &S, QualType TargetType, + ObjCArrayLiteral *ArrayLiteral) { if (!S.NSArrayDecl) return; @@ -9450,8 +9535,9 @@ void checkObjCArrayLiteral(Sema &S, QualType TargetType, /// Check an Objective-C dictionary literal being converted to the given /// target type. -void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, - ObjCDictionaryLiteral *DictionaryLiteral) { +static void +checkObjCDictionaryLiteral(Sema &S, QualType TargetType, + ObjCDictionaryLiteral *DictionaryLiteral) { if (!S.NSDictionaryDecl) return; @@ -9479,8 +9565,8 @@ void checkObjCDictionaryLiteral(Sema &S, QualType TargetType, // Helper function to filter out cases for constant width constant conversion. // Don't warn on char array initialization or for non-decimal values. -bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC) { +static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC) { // If initializing from a constant, and the constant starts with '0', // then it is a binary, octal, or hexadecimal. Allow these constants // to fill all the bits, even if there is a sign change. @@ -9503,8 +9589,9 @@ bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T, return true; } -void CheckImplicitConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC, bool *ICContext = nullptr) { +static void +CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, + bool *ICContext = nullptr) { if (E->isTypeDependent() || E->isValueDependent()) return; const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); @@ -9772,11 +9859,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } -void CheckConditionalOperator(Sema &S, ConditionalOperator *E, - SourceLocation CC, QualType T); +static void CheckConditionalOperator(Sema &S, ConditionalOperator *E, + SourceLocation CC, QualType T); -void CheckConditionalOperand(Sema &S, Expr *E, QualType T, - SourceLocation CC, bool &ICContext) { +static void CheckConditionalOperand(Sema &S, Expr *E, QualType T, + SourceLocation CC, bool &ICContext) { E = E->IgnoreParenImpCasts(); if (isa<ConditionalOperator>(E)) @@ -9787,8 +9874,8 @@ void CheckConditionalOperand(Sema &S, Expr *E, QualType T, return CheckImplicitConversion(S, E, T, CC, &ICContext); } -void CheckConditionalOperator(Sema &S, ConditionalOperator *E, - SourceLocation CC, QualType T) { +static void CheckConditionalOperator(Sema &S, ConditionalOperator *E, + SourceLocation CC, QualType T) { AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc()); bool Suspicious = false; @@ -9817,7 +9904,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, /// CheckBoolLikeConversion - Check conversion of given expression to boolean. /// Input argument E is a logical expression. -void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { +static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { if (S.getLangOpts().Bool) return; CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC); @@ -9826,7 +9913,8 @@ void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { /// AnalyzeImplicitConversions - Find and report any interesting /// implicit conversions in the given expression. There are a couple /// of competing diagnostics here, -Wconversion and -Wsign-compare. -void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { +static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, + SourceLocation CC) { QualType T = OrigE->getType(); Expr *E = OrigE->IgnoreParenImpCasts(); @@ -9919,8 +10007,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { ::CheckBoolLikeConversion(S, U->getSubExpr(), CC); } -} // end anonymous namespace - /// Diagnose integer type and any valid implicit convertion to it. static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) { // Taking into account implicit conversions, @@ -10226,10 +10312,11 @@ void Sema::CheckForIntOverflow (Expr *E) { } namespace { + /// \brief Visitor for expressions which looks for unsequenced operations on the /// same object. class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { - typedef EvaluatedExprVisitor<SequenceChecker> Base; + using Base = EvaluatedExprVisitor<SequenceChecker>; /// \brief A tree of sequenced regions within an expression. Two regions are /// unsequenced if one is an ancestor or a descendent of the other. When we @@ -10248,11 +10335,14 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { /// \brief A region within an expression which may be sequenced with respect /// to some other region. class Seq { - explicit Seq(unsigned N) : Index(N) {} - unsigned Index; friend class SequenceTree; + + unsigned Index = 0; + + explicit Seq(unsigned N) : Index(N) {} + public: - Seq() : Index(0) {} + Seq() = default; }; SequenceTree() { Values.push_back(Value(0)); } @@ -10296,16 +10386,18 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { }; /// An object for which we can track unsequenced uses. - typedef NamedDecl *Object; + using Object = NamedDecl *; /// Different flavors of object usage which we track. We only track the /// least-sequenced usage of each kind. enum UsageKind { /// A read of an object. Multiple unsequenced reads are OK. UK_Use, + /// A modification of an object which is sequenced before the value /// computation of the expression, such as ++n in C++. UK_ModAsValue, + /// A modification of an object which is not sequenced before the value /// computation of the expression, such as n++. UK_ModAsSideEffect, @@ -10314,29 +10406,37 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { }; struct Usage { - Usage() : Use(nullptr), Seq() {} - Expr *Use; + Expr *Use = nullptr; SequenceTree::Seq Seq; + + Usage() = default; }; struct UsageInfo { - UsageInfo() : Diagnosed(false) {} Usage Uses[UK_Count]; + /// Have we issued a diagnostic for this variable already? - bool Diagnosed; + bool Diagnosed = false; + + UsageInfo() = default; }; - typedef llvm::SmallDenseMap<Object, UsageInfo, 16> UsageInfoMap; + using UsageInfoMap = llvm::SmallDenseMap<Object, UsageInfo, 16>; Sema &SemaRef; + /// Sequenced regions within the expression. SequenceTree Tree; + /// Declaration modifications and references which we have seen. UsageInfoMap UsageMap; + /// The region we are currently within. SequenceTree::Seq Region; + /// Filled in with declarations which were modified as a side-effect /// (that is, post-increment operations). - SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect; + SmallVectorImpl<std::pair<Object, Usage>> *ModAsSideEffect = nullptr; + /// Expressions to check later. We defer checking these to reduce /// stack usage. SmallVectorImpl<Expr *> &WorkList; @@ -10351,6 +10451,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { : Self(Self), OldModAsSideEffect(Self.ModAsSideEffect) { Self.ModAsSideEffect = &ModAsSideEffect; } + ~SequencedSubexpression() { for (auto &M : llvm::reverse(ModAsSideEffect)) { UsageInfo &U = Self.UsageMap[M.first]; @@ -10363,7 +10464,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { SequenceChecker &Self; SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect; - SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect; + SmallVectorImpl<std::pair<Object, Usage>> *OldModAsSideEffect; }; /// RAII object wrapping the visitation of a subexpression which we might @@ -10373,9 +10474,10 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { class EvaluationTracker { public: EvaluationTracker(SequenceChecker &Self) - : Self(Self), Prev(Self.EvalTracker), EvalOK(true) { + : Self(Self), Prev(Self.EvalTracker) { Self.EvalTracker = this; } + ~EvaluationTracker() { Self.EvalTracker = Prev; if (Prev) @@ -10392,8 +10494,8 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { private: SequenceChecker &Self; EvaluationTracker *Prev; - bool EvalOK; - } *EvalTracker; + bool EvalOK = true; + } *EvalTracker = nullptr; /// \brief Find the object which is produced by the specified expression, /// if any. @@ -10427,6 +10529,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { U.Seq = Region; } } + /// \brief Check whether a modification or use conflicts with a prior usage. void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind, bool IsModMod) { @@ -10454,6 +10557,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { // Uses conflict with other modifications. checkUsage(O, U, Use, UK_ModAsValue, false); } + void notePostUse(Object O, Expr *Use) { UsageInfo &U = UsageMap[O]; checkUsage(O, U, Use, UK_ModAsSideEffect, false); @@ -10466,6 +10570,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { checkUsage(O, U, Mod, UK_ModAsValue, true); checkUsage(O, U, Mod, UK_Use, false); } + void notePostMod(Object O, Expr *Use, UsageKind UK) { UsageInfo &U = UsageMap[O]; checkUsage(O, U, Use, UK_ModAsSideEffect, true); @@ -10474,8 +10579,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { public: SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList) - : Base(S.Context), SemaRef(S), Region(Tree.root()), - ModAsSideEffect(nullptr), WorkList(WorkList), EvalTracker(nullptr) { + : Base(S.Context), SemaRef(S), Region(Tree.root()), WorkList(WorkList) { Visit(E); } @@ -10709,7 +10813,8 @@ public: Tree.merge(Elts[I]); } }; -} // end anonymous namespace + +} // namespace void Sema::CheckUnsequencedOperations(Expr *E) { SmallVector<Expr *, 8> WorkList; @@ -11126,19 +11231,22 @@ void Sema::CheckArrayAccess(const Expr *expr) { //===--- CHECK: Objective-C retain cycles ----------------------------------// namespace { - struct RetainCycleOwner { - RetainCycleOwner() : Variable(nullptr), Indirect(false) {} - VarDecl *Variable; - SourceRange Range; - SourceLocation Loc; - bool Indirect; - void setLocsFrom(Expr *e) { - Loc = e->getExprLoc(); - Range = e->getSourceRange(); - } - }; -} // end anonymous namespace +struct RetainCycleOwner { + VarDecl *Variable = nullptr; + SourceRange Range; + SourceLocation Loc; + bool Indirect = false; + + RetainCycleOwner() = default; + + void setLocsFrom(Expr *e) { + Loc = e->getExprLoc(); + Range = e->getSourceRange(); + } +}; + +} // namespace /// Consider whether capturing the given variable can possibly lead to /// a retain cycle. @@ -11235,15 +11343,16 @@ static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { } namespace { + struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> { - FindCaptureVisitor(ASTContext &Context, VarDecl *variable) - : EvaluatedExprVisitor<FindCaptureVisitor>(Context), - Context(Context), Variable(variable), Capturer(nullptr), - VarWillBeReased(false) {} ASTContext &Context; VarDecl *Variable; - Expr *Capturer; - bool VarWillBeReased; + Expr *Capturer = nullptr; + bool VarWillBeReased = false; + + FindCaptureVisitor(ASTContext &Context, VarDecl *variable) + : EvaluatedExprVisitor<FindCaptureVisitor>(Context), + Context(Context), Variable(variable) {} void VisitDeclRefExpr(DeclRefExpr *ref) { if (ref->getDecl() == Variable && !Capturer) @@ -11268,6 +11377,7 @@ namespace { if (OVE->getSourceExpr()) Visit(OVE->getSourceExpr()); } + void VisitBinaryOperator(BinaryOperator *BinOp) { if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) return; @@ -11284,7 +11394,8 @@ namespace { } } }; -} // end anonymous namespace + +} // namespace /// Check whether the given argument is a block which captures a /// variable. @@ -11691,16 +11802,14 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, //===--- CHECK: Empty statement body (-Wempty-body) ---------------------===// -namespace { -bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, - SourceLocation StmtLoc, - const NullStmt *Body) { +static bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, + SourceLocation StmtLoc, + const NullStmt *Body) { // Do not warn if the body is a macro that expands to nothing, e.g: // // #define CALL(x) // if (condition) // CALL(0); - // if (Body->hasLeadingEmptyMacro()) return false; @@ -11723,7 +11832,6 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, return true; } -} // end anonymous namespace void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body, @@ -11903,12 +12011,10 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, //===--- Layout compatibility ----------------------------------------------// -namespace { - -bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2); +static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2); /// \brief Check if two enumeration types are layout-compatible. -bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) { +static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) { // C++11 [dcl.enum] p8: // Two enumeration types are layout-compatible if they have the same // underlying type. @@ -11917,7 +12023,8 @@ bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) { } /// \brief Check if two fields are layout-compatible. -bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1, FieldDecl *Field2) { +static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1, + FieldDecl *Field2) { if (!isLayoutCompatible(C, Field1->getType(), Field2->getType())) return false; @@ -11938,9 +12045,8 @@ bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1, FieldDecl *Field2) { /// \brief Check if two standard-layout structs are layout-compatible. /// (C++11 [class.mem] p17) -bool isLayoutCompatibleStruct(ASTContext &C, - RecordDecl *RD1, - RecordDecl *RD2) { +static bool isLayoutCompatibleStruct(ASTContext &C, RecordDecl *RD1, + RecordDecl *RD2) { // If both records are C++ classes, check that base classes match. if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1)) { // If one of records is a CXXRecordDecl we are in C++ mode, @@ -11983,9 +12089,8 @@ bool isLayoutCompatibleStruct(ASTContext &C, /// \brief Check if two standard-layout unions are layout-compatible. /// (C++11 [class.mem] p18) -bool isLayoutCompatibleUnion(ASTContext &C, - RecordDecl *RD1, - RecordDecl *RD2) { +static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1, + RecordDecl *RD2) { llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields; for (auto *Field2 : RD2->fields()) UnmatchedFields.insert(Field2); @@ -12010,7 +12115,8 @@ bool isLayoutCompatibleUnion(ASTContext &C, return UnmatchedFields.empty(); } -bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1, RecordDecl *RD2) { +static bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1, + RecordDecl *RD2) { if (RD1->isUnion() != RD2->isUnion()) return false; @@ -12021,7 +12127,7 @@ bool isLayoutCompatible(ASTContext &C, RecordDecl *RD1, RecordDecl *RD2) { } /// \brief Check if two types are layout-compatible in C++11 sense. -bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) { +static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) { if (T1.isNull() || T2.isNull()) return false; @@ -12055,11 +12161,9 @@ bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) { return false; } -} // end anonymous namespace //===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----// -namespace { /// \brief Given a type tag expression find the type tag itself. /// /// \param TypeExpr Type tag expression, as it appears in user's code. @@ -12067,8 +12171,8 @@ namespace { /// \param VD Declaration of an identifier that appears in a type tag. /// /// \param MagicValue Type tag magic value. -bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, - const ValueDecl **VD, uint64_t *MagicValue) { +static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, + const ValueDecl **VD, uint64_t *MagicValue) { while(true) { if (!TypeExpr) return false; @@ -12143,7 +12247,7 @@ bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, /// \param TypeInfo Information about the corresponding C type. /// /// \returns true if the corresponding C type was found. -bool GetMatchingCType( +static bool GetMatchingCType( const IdentifierInfo *ArgumentKind, const Expr *TypeExpr, const ASTContext &Ctx, const llvm::DenseMap<Sema::TypeTagMagicValue, @@ -12186,7 +12290,6 @@ bool GetMatchingCType( TypeInfo = I->second; return true; } -} // end anonymous namespace void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, uint64_t MagicValue, QualType Type, @@ -12201,8 +12304,7 @@ void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, TypeTagData(Type, LayoutCompatible, MustBeNull); } -namespace { -bool IsSameCharType(QualType T1, QualType T2) { +static bool IsSameCharType(QualType T1, QualType T2) { const BuiltinType *BT1 = T1->getAs<BuiltinType>(); if (!BT1) return false; @@ -12219,7 +12321,6 @@ bool IsSameCharType(QualType T1, QualType T2) { (T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) || (T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar); } -} // end anonymous namespace void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, const Expr * const *ExprArgs) { @@ -12448,8 +12549,8 @@ void Sema::RefersToMemberWithReducedAlignment( void Sema::CheckAddressOfPackedMember(Expr *rhs) { using namespace std::placeholders; + RefersToMemberWithReducedAlignment( rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1, _2, _3, _4)); } - |