1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 public class Main {
18   static Main obj;
19   // Make 'doCheck' volatile to prevent optimizations
20   // in $noinline$bar like LICM that could hoist the null check
21   // out of the loop.
22   static volatile boolean doCheck = true;
23 
24   float floatField;
25   int intField;
26 
main(String[] args)27   public static void main(String[] args) {
28     try {
29       $noinline$bar();
30       throw new Error("Expected NPE");
31     } catch (NullPointerException e) {
32       check(e, 29, 52, "$noinline$bar");
33     }
34 
35     try {
36       $noinline$foo();
37       throw new Error("Expected NPE");
38     } catch (NullPointerException e) {
39       check(e, 36, 44, "$noinline$foo");
40     }
41   }
42 
$noinline$foo()43   public static float $noinline$foo() {
44     int v1 = obj.intField;
45     float v2 = obj.floatField;
46     return v2;
47   }
48 
$noinline$bar()49   public static float $noinline$bar() {
50     float a = 0;
51     while (doCheck) {
52       float f = obj.floatField;
53       int i = obj.intField;
54       a = (float)i + f;
55     }
56     return a;
57   }
58 
check(NullPointerException npe, int mainLine, int methodLine, String methodName)59   static void check(NullPointerException npe, int mainLine, int methodLine, String methodName) {
60     StackTraceElement[] trace = npe.getStackTrace();
61     checkElement(trace[0], "Main", methodName, "Main.java", methodLine);
62     checkElement(trace[1], "Main", "main", "Main.java", mainLine);
63   }
64 
checkElement(StackTraceElement element, String declaringClass, String methodName, String fileName, int lineNumber)65   static void checkElement(StackTraceElement element,
66                            String declaringClass, String methodName,
67                            String fileName, int lineNumber) {
68     assertEquals(declaringClass, element.getClassName());
69     assertEquals(methodName, element.getMethodName());
70     assertEquals(fileName, element.getFileName());
71     assertEquals(lineNumber, element.getLineNumber());
72   }
73 
assertEquals(Object expected, Object actual)74   static void assertEquals(Object expected, Object actual) {
75     if (!expected.equals(actual)) {
76       String msg = "Expected \"" + expected + "\" but got \"" + actual + "\"";
77       throw new AssertionError(msg);
78     }
79   }
80 
assertEquals(int expected, int actual)81   static void assertEquals(int expected, int actual) {
82     if (expected != actual) {
83       throw new AssertionError("Expected " + expected + " got " + actual);
84     }
85   }
86 }
87