brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.9 KiB · acd33e7 Raw
334 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++14 -triple amdgcn-unknown-unknown \2// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\3// RUN: -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s -check-prefix=X86-CHECK4//5// RUN: %clang_analyze_cc1 -std=c++14 -triple amdgcn-unknown-unknown \6// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\7// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=false\8// RUN:  -analyzer-output=text -verify -DX86 -DNOT_SUPPRESSED %s 2>&1 | FileCheck %s -check-prefix=X86-CHECK9//10// RUN: %clang_analyze_cc1 -std=c++14 -triple amdgcn-unknown-unknown \11// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\12// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=true\13// RUN:  -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s -check-prefix=X86-CHECK14//15// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \16// RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\17// RUN:  -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s --check-prefix=X86-CHECK18//19// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \20// RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\21// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=true\22// RUN:  -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s --check-prefix=X86-CHECK-SUPPRESSED23//24// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \25// RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\26// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=false\27// RUN:  -analyzer-output=text -verify -DX86 -DNOT_SUPPRESSED %s 2>&1 | FileCheck %s --check-prefix=X86-CHECK28//29// RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \30// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\31// RUN: -analyzer-output=text -verify -DMIPS %s 2>&132//33// RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \34// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\35// RUN: -analyzer-config suppress-dereferences-from-any-address-space=false\36// RUN: -analyzer-output=text -verify -DMIPS %s 2>&137//38// RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \39// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\40// RUN: -analyzer-config suppress-dereferences-from-any-address-space=true\41// RUN: -analyzer-output=text -verify -DMIPS_SUPPRESSED %s42 43#include "Inputs/llvm.h"44 45// The amggcn triple case uses an intentionally different address space.46// The core.NullDereference checker intentionally ignores checks47// that use address spaces, so the case is differentiated here.48//49// From https://llvm.org/docs/AMDGPUUsage.html#address-spaces,50// select address space 3 (local), since the pointer size is51// different than Generic.52#define DEVICE __attribute__((address_space(3)))53 54namespace clang {55struct Shape {56  template <typename T>57  const T *castAs() const;58 59  template <typename T>60  const T *getAs() const;61};62class Triangle : public Shape {};63class Rectangle : public Shape {};64class Hexagon : public Shape {};65class Circle : public Shape {};66} // namespace clang67 68using namespace llvm;69using namespace clang;70 71void clang_analyzer_printState();72 73#if defined(X86)74void evalReferences(const Shape &S) {75  const auto &C = dyn_cast<Circle>(S);76  // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}}77  // expected-note@-2 {{Dereference of null pointer}}78  // expected-warning@-3 {{Dereference of null pointer}}79  clang_analyzer_printState();80  // XX86-CHECK:      "dynamic_types": [81  // XX86-CHECK-NEXT:   { "region": "SymRegion{reg_$0<const struct clang::Shape & S>}", "dyn_type": "const class clang::Circle &", "sub_classable": true }82  (void)C;83}84#if defined(SUPPRESSED)85void evalReferences_addrspace(const Shape &S) {86  const auto &C = dyn_cast<DEVICE Circle>(S);87  clang_analyzer_printState();88  // X86-CHECK-SUPPRESSED: "dynamic_types": [89  // X86-CHECK-SUPPRESSED-NEXT: { "region": "SymRegion{reg_$0<const Shape & S>}", "dyn_type": "const __attribute__((address_space(3))) class clang::Circle &", "sub_classable": true }90  (void)C;91}92#endif93#if defined(NOT_SUPPRESSED)94void evalReferences_addrspace(const Shape &S) {95  const auto &C = dyn_cast<DEVICE Circle>(S);96  // expected-note@-1 {{Assuming 'S' is not a 'const __attribute__((address_space(3))) class clang::Circle &'}}97  // expected-note@-2 {{Dereference of null pointer}}98  // expected-warning@-3 {{Dereference of null pointer}}99  clang_analyzer_printState();100  // X86-CHECK: "dynamic_types": [101  // X86-CHECK-NEXT: { "region": "SymRegion{reg_$0<const Shape & S>}", "dyn_type": "const __attribute__((address_space(3))) class clang::Circle &", "sub_classable": true }102  (void)C;103}104#endif105#elif defined(MIPS)106void evalReferences(const Shape &S) {107  const auto &C = dyn_cast<Circle>(S);108  // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}}109  // expected-note@-2 {{Dereference of null pointer}}110  // expected-warning@-3 {{Dereference of null pointer}}111}112#if defined(MIPS_SUPPRESSED)113void evalReferences_addrspace(const Shape &S) {114  const auto &C = dyn_cast<DEVICE Circle>(S);115  (void)C;116}117#endif118#endif119 120void evalNonNullParamNonNullReturnReference(const Shape &S) {121  const auto *C = dyn_cast_or_null<Circle>(S);122  // expected-note@-1 {{'C' initialized here}}123 124  if (!dyn_cast_or_null<Circle>(C)) {125    // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}}126    // expected-note@-2 {{Taking false branch}}127    return;128  }129 130  if (dyn_cast_or_null<Triangle>(C)) {131    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}}132    // expected-note@-2 {{Taking false branch}}133    return;134  }135 136  if (dyn_cast_or_null<Rectangle>(C)) {137    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}}138    // expected-note@-2 {{Taking false branch}}139    return;140  }141 142  if (dyn_cast_or_null<Hexagon>(C)) {143    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}}144    // expected-note@-2 {{Taking false branch}}145    return;146  }147 148  if (isa<Triangle>(C)) {149    // expected-note@-1 {{'C' is not a 'Triangle'}}150    // expected-note@-2 {{Taking false branch}}151    return;152  }153 154  if (isa<Triangle, Rectangle>(C)) {155    // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}156    // expected-note@-2 {{Taking false branch}}157    return;158  }159 160  if (isa<Triangle, Rectangle, Hexagon>(C)) {161    // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}162    // expected-note@-2 {{Taking false branch}}163    return;164  }165 166  if (isa<Circle, Rectangle, Hexagon>(C)) {167    // expected-note@-1 {{'C' is a 'Circle'}}168    // expected-note@-2 {{Taking true branch}}169 170    (void)(1 / !C);171    // expected-note@-1 {{'C' is non-null}}172    // expected-note@-2 {{Division by zero}}173    // expected-warning@-3 {{Division by zero}}174  }175}176 177void evalNonNullParamNonNullReturn(const Shape *S) {178  const auto *C = cast<Circle>(S);179  // expected-note@-1 {{'S' is a 'const class clang::Circle *'}}180  // expected-note@-2 {{'C' initialized here}}181 182  if (!dyn_cast_or_null<Circle>(C)) {183    // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}}184    // expected-note@-2 {{Taking false branch}}185    return;186  }187 188  if (dyn_cast_or_null<Triangle>(C)) {189    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}}190    // expected-note@-2 {{Taking false branch}}191    return;192  }193 194  if (dyn_cast_or_null<Rectangle>(C)) {195    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}}196    // expected-note@-2 {{Taking false branch}}197    return;198  }199 200  if (dyn_cast_or_null<Hexagon>(C)) {201    // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}}202    // expected-note@-2 {{Taking false branch}}203    return;204  }205 206  if (isa<Triangle>(C)) {207    // expected-note@-1 {{'C' is not a 'Triangle'}}208    // expected-note@-2 {{Taking false branch}}209    return;210  }211 212  if (isa<Triangle, Rectangle>(C)) {213    // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}214    // expected-note@-2 {{Taking false branch}}215    return;216  }217 218  if (isa<Triangle, Rectangle, Hexagon>(C)) {219    // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}220    // expected-note@-2 {{Taking false branch}}221    return;222  }223 224  if (isa<Circle, Rectangle, Hexagon>(C)) {225    // expected-note@-1 {{'C' is a 'Circle'}}226    // expected-note@-2 {{Taking true branch}}227 228    (void)(1 / !C);229    // expected-note@-1 {{'C' is non-null}}230    // expected-note@-2 {{Division by zero}}231    // expected-warning@-3 {{Division by zero}}232  }233}234 235void evalNonNullParamNullReturn(const Shape *S) {236  const auto *C = dyn_cast_or_null<Circle>(S);237  // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}}238 239  if (const auto *T = dyn_cast_or_null<Triangle>(S)) {240    // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}}241    // expected-note@-2 {{'T' initialized here}}242    // expected-note@-3 {{'T' is non-null}}243    // expected-note@-4 {{Taking true branch}}244 245    (void)(1 / !T);246    // expected-note@-1 {{'T' is non-null}}247    // expected-note@-2 {{Division by zero}}248    // expected-warning@-3 {{Division by zero}}249  }250}251 252void evalNullParamNullReturn(const Shape *S) {253  const auto *C = dyn_cast_or_null<Circle>(S);254  // expected-note@-1 {{Assuming null pointer is passed into cast}}255  // expected-note@-2 {{'C' initialized to a null pointer value}}256 257  (void)(1 / (bool)C);258  // expected-note@-1 {{Division by zero}}259  // expected-warning@-2 {{Division by zero}}260}261 262void evalZeroParamNonNullReturnPointer(const Shape *S) {263  const auto *C = S->castAs<Circle>();264  // expected-note@-1 {{'S' is a 'const class clang::Circle *'}}265  // expected-note@-2 {{'C' initialized here}}266 267  (void)(1 / !C);268  // expected-note@-1 {{'C' is non-null}}269  // expected-note@-2 {{Division by zero}}270  // expected-warning@-3 {{Division by zero}}271}272 273void evalZeroParamNonNullReturn(const Shape &S) {274  const auto *C = S.castAs<Circle>();275  // expected-note@-1 {{'C' initialized here}}276 277  (void)(1 / !C);278  // expected-note@-1 {{'C' is non-null}}279  // expected-note@-2 {{Division by zero}}280  // expected-warning@-3 {{Division by zero}}281}282 283void evalZeroParamNullReturn(const Shape *S) {284  const auto &C = S->getAs<Circle>();285  // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}}286  // expected-note@-2 {{Storing null pointer value}}287  // expected-note@-3 {{'C' initialized here}}288 289  if (!dyn_cast_or_null<Triangle>(S)) {290    // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}}291    // expected-note@-2 {{Taking false branch}}292    return;293  }294 295  if (!dyn_cast_or_null<Triangle>(S)) {296    // expected-note@-1 {{'S' is a 'Triangle'}}297    // expected-note@-2 {{Taking false branch}}298    return;299  }300 301  (void)(1 / (bool)C);302  // expected-note@-1 {{Division by zero}}303  // expected-warning@-2 {{Division by zero}}304}305 306// don't crash307// CastValueChecker was using QualType()->getPointeeCXXRecordDecl(), in308// getNoteTag which evaluated to nullptr, then crashed when attempting to309// deref an invocation to getNameAsString(). The fix is to use310// QualType().getAsString().311//312// Example:313// std::string CastToName =314//       CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()315//                : CastToTy->getPointeeCXXRecordDecl()->getNameAsString();316// Changed to:317// std::string CastToName =318//       CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()319//                : CastToTy.getAsString();320namespace llvm {321template <typename, typename a> void isa(a &);322template <typename> class PointerUnion {323public:324  template <typename T> T *getAs() {325    (void)isa<int>(*this);326    return nullptr;327  }328};329class LLVMContext {330  PointerUnion<LLVMContext> c;331  void d() { c.getAs<int>(); }332};333} // namespace llvm334